From 3638c658d60ca55ef99fc26e074ecdc5e04de3f9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 23 Aug 2008 08:48:19 +0000 Subject: [PATCH] - Added and fixed Boss death submission for random spawner. - Added functions to FActorInfo that can set the damage factors and pain chances to reduce the chance of new errors when working with these features. - Fixed: The handling of the deprecated FIRERESIST flag didn't work. There were 3 problems: * Actor defaults have no class information so HandleDeprecatedFlags needs to be passed a pointer to the ActorInfo. * The DamageFactors list is only created when needed so the code needs to check if it already exists. * damage factors are stored as fixed_t but this set a float. - Added a traditional Strife color set for the automap. SVN r1183 (trunk) --- docs/rh-log.txt | 16 +++ src/am_map.cpp | 146 +++++++++++++++++---------- src/g_shared/a_randomspawner.cpp | 41 ++++++-- src/info.cpp | 37 +++++++ src/info.h | 2 + src/m_options.cpp | 9 +- src/thingdef/thingdef_properties.cpp | 24 ++--- 7 files changed, 193 insertions(+), 82 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ee22a3f80..9f1caebaf 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,16 @@ +August 22, 2008 (Changes by Graf Zahl) +- Added and fixed Boss death submission for random spawner. +- Added functions to FActorInfo that can set the damage factors and + pain chances to reduce the chance of new errors when working with + these features. +- Fixed: The handling of the deprecated FIRERESIST flag didn't work. + There were 3 problems: + * Actor defaults have no class information so HandleDeprecatedFlags + needs to be passed a pointer to the ActorInfo. + * The DamageFactors list is only created when needed so the code needs to + check if it already exists. + * damage factors are stored as fixed_t but this set a float. + August 22, 2008 - Fixed: Timidity::Renderer::reset_voices() must completely zero the voices. Because this wasn't done, note_on() could try to access @@ -5,6 +18,9 @@ August 22, 2008 random memory. There may be other places where it's a problem, but this is where I noticed it, by chance. +August 21, 2008 (Changes by Graf Zahl) +- Added a traditional Strife color set for the automap. + August 21, 2008 (Changes by Graf Zahl) - Fixed: The conversion of the strings in wbstartstruct_t to FStrings caused crashes when reloading the hub data. diff --git a/src/am_map.cpp b/src/am_map.cpp index f3aaf19b4..2b392461f 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -91,6 +91,15 @@ static BYTE DoomPaletteVals[11*3] = 0x80,0x80,0x80, 0x6c,0x6c,0x6c }; +static AMColor StrifeColors[11]; +static BYTE StrifePaletteVals[11*3] = +{ + 0x00,0x00,0x00, 239, 239, 0, 0x10,0x10,0x10, + 199, 195, 195, 119, 115, 115, 55, 59, 91, + 119, 115, 115, 0xfc,0x00,0x00, 0x4c,0x4c,0x4c, + 0x80,0x80,0x80, 0x6c,0x6c,0x6c +}; + #define MAPBITS 12 #define MapDiv SafeDivScale12 #define MapMul MulScale12 @@ -122,7 +131,7 @@ CVAR (Bool, am_showmonsters, true, CVAR_ARCHIVE); CVAR (Bool, am_showitems, false, CVAR_ARCHIVE); CVAR (Bool, am_showtime, true, CVAR_ARCHIVE); CVAR (Bool, am_showtotaltime, false, CVAR_ARCHIVE); -CVAR (Bool, am_usecustomcolors, true, CVAR_ARCHIVE); +CVAR (Int, am_colorset, 0, CVAR_ARCHIVE); CVAR (Color, am_backcolor, 0x6c5440, CVAR_ARCHIVE); CVAR (Color, am_yourcolor, 0xfce8d8, CVAR_ARCHIVE); CVAR (Color, am_wallcolor, 0x2c1808, CVAR_ARCHIVE); @@ -648,6 +657,7 @@ static void AM_initColors (bool overlayed) for (i = j = 0; i < 11; i++, j += 3) { DoomColors[i].FromRGB(DoomPaletteVals[j], DoomPaletteVals[j+1], DoomPaletteVals[j+2]); + StrifeColors[i].FromRGB(StrifePaletteVals[j], StrifePaletteVals[j+1], StrifePaletteVals[j+2]); } } @@ -667,62 +677,88 @@ static void AM_initColors (bool overlayed) InterTeleportColor.FromCVar (am_ovtelecolor); IntraTeleportColor = InterTeleportColor; } - else if (am_usecustomcolors) + else switch(am_colorset) { - /* Use the custom colors in the am_* cvars */ - Background.FromCVar (am_backcolor); - YourColor.FromCVar (am_yourcolor); - SecretWallColor.FromCVar (am_secretwallcolor); - WallColor.FromCVar (am_wallcolor); - TSWallColor.FromCVar (am_tswallcolor); - FDWallColor.FromCVar (am_fdwallcolor); - CDWallColor.FromCVar (am_cdwallcolor); - ThingColor_Item.FromCVar (am_thingcolor_item); - ThingColor_Friend.FromCVar (am_thingcolor_friend); - ThingColor_Monster.FromCVar (am_thingcolor_monster); - ThingColor.FromCVar (am_thingcolor); - GridColor.FromCVar (am_gridcolor); - XHairColor.FromCVar (am_xhaircolor); - NotSeenColor.FromCVar (am_notseencolor); - LockedColor.FromCVar (am_lockedcolor); - InterTeleportColor.FromCVar (am_interlevelcolor); - IntraTeleportColor.FromCVar (am_intralevelcolor); - SecretSectorColor.FromCVar (am_secretsectorcolor); + default: + { + /* Use the custom colors in the am_* cvars */ + Background.FromCVar (am_backcolor); + YourColor.FromCVar (am_yourcolor); + SecretWallColor.FromCVar (am_secretwallcolor); + WallColor.FromCVar (am_wallcolor); + TSWallColor.FromCVar (am_tswallcolor); + FDWallColor.FromCVar (am_fdwallcolor); + CDWallColor.FromCVar (am_cdwallcolor); + ThingColor_Item.FromCVar (am_thingcolor_item); + ThingColor_Friend.FromCVar (am_thingcolor_friend); + ThingColor_Monster.FromCVar (am_thingcolor_monster); + ThingColor.FromCVar (am_thingcolor); + GridColor.FromCVar (am_gridcolor); + XHairColor.FromCVar (am_xhaircolor); + NotSeenColor.FromCVar (am_notseencolor); + LockedColor.FromCVar (am_lockedcolor); + InterTeleportColor.FromCVar (am_interlevelcolor); + IntraTeleportColor.FromCVar (am_intralevelcolor); + SecretSectorColor.FromCVar (am_secretsectorcolor); - DWORD ba = am_backcolor; + DWORD ba = am_backcolor; - int r = RPART(ba) - 16; - int g = GPART(ba) - 16; - int b = BPART(ba) - 16; + int r = RPART(ba) - 16; + int g = GPART(ba) - 16; + int b = BPART(ba) - 16; - if (r < 0) - r += 32; - if (g < 0) - g += 32; - if (b < 0) - b += 32; + if (r < 0) + r += 32; + if (g < 0) + g += 32; + if (b < 0) + b += 32; - AlmostBackground.FromRGB(r, g, b); - } - else - { // Use colors corresponding to the original Doom's - Background = DoomColors[0]; - YourColor = DoomColors[1]; - AlmostBackground = DoomColors[2]; - SecretSectorColor = - SecretWallColor = - WallColor = DoomColors[3]; - TSWallColor = DoomColors[4]; - FDWallColor = DoomColors[5]; - LockedColor = - CDWallColor = DoomColors[6]; - ThingColor_Item = - ThingColor_Friend = - ThingColor_Monster = - ThingColor = DoomColors[7]; - GridColor = DoomColors[8]; - XHairColor = DoomColors[9]; - NotSeenColor = DoomColors[10]; + AlmostBackground.FromRGB(r, g, b); + break; + } + + case 1: // Doom + // Use colors corresponding to the original Doom's + Background = DoomColors[0]; + YourColor = DoomColors[1]; + AlmostBackground = DoomColors[2]; + SecretSectorColor = + SecretWallColor = + WallColor = DoomColors[3]; + TSWallColor = DoomColors[4]; + FDWallColor = DoomColors[5]; + LockedColor = + CDWallColor = DoomColors[6]; + ThingColor_Item = + ThingColor_Friend = + ThingColor_Monster = + ThingColor = DoomColors[7]; + GridColor = DoomColors[8]; + XHairColor = DoomColors[9]; + NotSeenColor = DoomColors[10]; + break; + + case 2: // Strife + // Use colors corresponding to the original Strife's + Background = StrifeColors[0]; + YourColor = StrifeColors[1]; + AlmostBackground = DoomColors[2]; + SecretSectorColor = + SecretWallColor = + WallColor = StrifeColors[3]; + TSWallColor = StrifeColors[4]; + FDWallColor = StrifeColors[5]; + LockedColor = + CDWallColor = StrifeColors[6]; + ThingColor_Item = + ThingColor_Friend = + ThingColor_Monster = + ThingColor = StrifeColors[7]; + GridColor = StrifeColors[8]; + XHairColor = StrifeColors[9]; + NotSeenColor = StrifeColors[10]; + break; } lastpal = palette; @@ -1348,7 +1384,7 @@ void AM_drawWalls (bool allmap) lines[i].special == Teleport_ZombieChanger || lines[i].special == Teleport_Line) && (lines[i].activation & SPAC_PlayerActivate) && - am_usecustomcolors) + am_colorset == 0) { // intra-level teleporters AM_drawMline(&l, IntraTeleportColor); } @@ -1356,7 +1392,7 @@ void AM_drawWalls (bool allmap) lines[i].special == Teleport_EndGame || lines[i].special == Exit_Normal || lines[i].special == Exit_Secret) && - am_usecustomcolors) + am_colorset == 0) { // inter-level/game-ending teleporters AM_drawMline(&l, InterTeleportColor); } @@ -1372,7 +1408,7 @@ void AM_drawWalls (bool allmap) lines[i].special == ACS_LockedExecuteDoor || (lines[i].special == Generic_Door && lines[i].args[4]!=0)) { - if (am_usecustomcolors) + if (am_colorset == 0) { int P_GetMapColorForLock(int lock); int lock; diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index 788e2d888..c35b09797 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -1,3 +1,8 @@ +/* +** a_randomspawner.cpp +** A thing that randomly spawns one item in a list of many, before disappearing. +*/ + #include "actor.h" #include "info.h" #include "m_random.h" @@ -10,12 +15,7 @@ #include "a_action.h" #include "thingdef/thingdef.h" -/* -- in the decorate definition define multiple drop items -- use the function GetDropItems to get the first drop item, then iterate over them and count how many dropitems are defined. -- with M_Random( ) % NUMBEROFDROPITEMS you get a random drop item number (let's call it n) -- use GetDropItems again to get the first drop item, then iterate to the n-th drop item -*/ +#define MAX_RANDOMSPAWNERS_RECURSION 32 // Should be largely more than enough, honestly. static FRandom pr_randomspawn("RandomSpawn"); class ARandomSpawner : public AActor @@ -32,10 +32,8 @@ class ARandomSpawner : public AActor Super::PostBeginPlay(); drop = di = GetDropItems(RUNTIME_TYPE(this)); - // Always make sure it actually exists. if (di != NULL) { - // First, we get the size of the array... while (di != NULL) { if (di->Name != NAME_None) @@ -59,7 +57,9 @@ class ARandomSpawner : public AActor } } // So now we can spawn the dropped item. - if (pr_randomspawn() <= di->probability) // prob 255 = always spawn, prob 0 = never spawn. + if (special1 >= MAX_RANDOMSPAWNERS_RECURSION) // Prevents infinite recursions + Spawn("Unknown", x, y, z, NO_REPLACE); // Show that there's a problem. + else if (pr_randomspawn() <= di->probability) // prob 255 = always spawn, prob 0 = never spawn. { newmobj = Spawn(di->Name, x, y, z, ALLOW_REPLACE); // copy everything relevant @@ -77,11 +77,32 @@ class ARandomSpawner : public AActor newmobj->momx = momx; newmobj->momy = momy; newmobj->momz = momz; + newmobj->master = master; // For things such as DamageMaster/DamageChildren, transfer mastery. + newmobj->target = target; + newmobj->tracer = tracer; newmobj->CopyFriendliness(this, false); + // Special1 is used to count how many recursions we're in. + if (newmobj->IsKindOf(PClass::FindClass("RandomSpawner"))) + newmobj->special1 = ++special1; + } } - Destroy(); + if ((newmobj != NULL) && ((newmobj->flags4 & MF4_BOSSDEATH) || (newmobj->flags2 & MF2_BOSS))) + this->target = newmobj; // If the spawned actor has either of those flags, it's a boss. + else Destroy(); // "else" because a boss-replacing spawner must wait until it can call A_BossDeath. } + + void Tick() // This function is needed for handling boss replacers + { + Super::Tick(); + if (target == NULL || target->health <= 0) + { + health = 0; + CALL_ACTION(A_BossDeath, this); + Destroy(); + } + } + }; IMPLEMENT_CLASS (ARandomSpawner) diff --git a/src/info.cpp b/src/info.cpp index ec854f728..cd4c294f4 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -293,6 +293,43 @@ FActorInfo *FActorInfo::GetReplacee () return rep; } +//========================================================================== +// +// +//========================================================================== + +void FActorInfo::SetDamageFactor(FName type, fixed_t factor) +{ + if (factor != FRACUNIT) + { + if (DamageFactors == NULL) DamageFactors=new DmgFactors; + DamageFactors->Insert(type, factor); + } + else + { + if (DamageFactors != NULL) + DamageFactors->Remove(type); + } +} + +//========================================================================== +// +// +//========================================================================== + +void FActorInfo::SetPainChance(FName type, int chance) +{ + if (chance >= 0) + { + if (PainChances == NULL) PainChances=new PainChanceList; + PainChances->Insert(type, MIN(chance, 255)); + } + else + { + if (PainChances != NULL) + PainChances->Remove(type); + } +} //========================================================================== // diff --git a/src/info.h b/src/info.h index 46a02cd9b..0f254b119 100644 --- a/src/info.h +++ b/src/info.h @@ -201,6 +201,8 @@ struct FActorInfo void BuildDefaults (); void ApplyDefaults (BYTE *defaults); void RegisterIDs (); + void SetDamageFactor(FName type, fixed_t factor); + void SetPainChance(FName type, int chance); FState *FindState (FName name) const; FState *FindState (int numnames, FName *names, bool exact=false) const; diff --git a/src/m_options.cpp b/src/m_options.cpp index 3abb41e17..b4ba51fee 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -101,6 +101,7 @@ EXTERN_CVAR (Bool, cl_run) EXTERN_CVAR (Int, crosshair) EXTERN_CVAR (Bool, freelook) EXTERN_CVAR (Int, sv_smartaim) +EXTERN_CVAR (Int, am_colorset) static void CalcIndent (menu_t *menu); @@ -544,7 +545,6 @@ static void StartMapColorsMenu (void); EXTERN_CVAR (Int, am_rotate) EXTERN_CVAR (Int, am_overlay) -EXTERN_CVAR (Bool, am_usecustomcolors) EXTERN_CVAR (Bool, am_showitems) EXTERN_CVAR (Bool, am_showmonsters) EXTERN_CVAR (Bool, am_showsecrets) @@ -554,8 +554,9 @@ EXTERN_CVAR (Bool, am_showtotaltime) EXTERN_CVAR (Bool, am_drawmapback) static value_t MapColorTypes[] = { - { 1, "Custom" }, - { 0, "Traditional Doom" } + { 0, "Custom" }, + { 1, "Traditional Doom" }, + { 2, "Traditional Strife" } }; static value_t SecretTypes[] = { @@ -577,7 +578,7 @@ static value_t OverlayTypes[] = { }; static menuitem_t AutomapItems[] = { - { discrete, "Map color set", {&am_usecustomcolors}, {2.0}, {0.0}, {0.0}, {MapColorTypes} }, + { discrete, "Map color set", {&am_colorset}, {3.0}, {0.0}, {0.0}, {MapColorTypes} }, { more, "Set custom colors", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t*)StartMapColorsMenu} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { discrete, "Rotate automap", {&am_rotate}, {3.0}, {0.0}, {0.0}, {RotateTypes} }, diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index d60bad331..2a3b21eb2 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -413,7 +413,7 @@ static flagdef *FindFlag (const PClass *type, const char *part1, const char *par // properties is not recommended // //=========================================================================== -static void HandleDeprecatedFlags(AActor *defaults, bool set, int index) +static void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index) { switch (index) { @@ -436,8 +436,8 @@ static void HandleDeprecatedFlags(AActor *defaults, bool set, int index) defaults->gravity = set? FRACUNIT/4 : FRACUNIT; break; case DEPF_FIRERESIST: - if (set) defaults->GetClass()->ActorInfo->DamageFactors->Insert("Fire", 0.5); - else defaults->GetClass()->ActorInfo->DamageFactors->Remove("Fire"); + info->SetDamageFactor(NAME_Fire, set? FRACUNIT/2 : FRACUNIT); + break; case DEPF_PICKUPFLASH: if (set) { @@ -468,22 +468,23 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) const char *dot = strchr (flagname, '.'); flagdef *fd; + const PClass *cls = self->GetClass(); if (dot != NULL) { FString part1(flagname, dot-flagname); - fd = FindFlag (self->GetClass(), part1, dot+1); + fd = FindFlag (cls, part1, dot+1); } else { - fd = FindFlag (self->GetClass(), flagname, NULL); + fd = FindFlag (cls, flagname, NULL); } if (fd != NULL) { if (fd->structoffset == -1) { - HandleDeprecatedFlags(self, expression, fd->flagbit); + HandleDeprecatedFlags(self, cls->ActorInfo, expression, fd->flagbit); } else { @@ -495,7 +496,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) } else { - Printf("Unknown flag '%s' in '%s'\n", flagname, self->GetClass()->TypeName.GetChars()); + Printf("Unknown flag '%s' in '%s'\n", flagname, cls->TypeName.GetChars()); } } @@ -520,7 +521,7 @@ void ParseActorFlag (FScanner &sc, Baggage &bag, int mod) AActor *defaults = (AActor*)bag.Info->Class->Defaults; if (fd->structoffset == -1) // this is a deprecated flag that has been changed into a real property { - HandleDeprecatedFlags(defaults, mod=='+', fd->flagbit); + HandleDeprecatedFlags(defaults, bag.Info, mod=='+', fd->flagbit); } else { @@ -963,9 +964,7 @@ static void ActorPainChance (FScanner &sc, AActor *defaults, Baggage &bag) else painType=sc.String; sc.MustGetToken(','); sc.MustGetNumber(); - - if (bag.Info->PainChances == NULL) bag.Info->PainChances=new PainChanceList; - (*bag.Info->PainChances)[painType] = (BYTE)sc.Number; + bag.Info->SetPainChance(painType, sc.Number); return; } defaults->PainChance=sc.Number; @@ -1636,7 +1635,6 @@ static void ActorDamageType (FScanner &sc, AActor *defaults, Baggage &bag) static void ActorDamageFactor (FScanner &sc, AActor *defaults, Baggage &bag) { sc.MustGetString (); - if (bag.Info->DamageFactors == NULL) bag.Info->DamageFactors=new DmgFactors; FName dmgType; if (sc.Compare("Normal")) dmgType = NAME_None; @@ -1644,7 +1642,7 @@ static void ActorDamageFactor (FScanner &sc, AActor *defaults, Baggage &bag) sc.MustGetToken(','); sc.MustGetFloat(); - (*bag.Info->DamageFactors)[dmgType]=(fixed_t)(sc.Float*FRACUNIT); + bag.Info->SetDamageFactor(dmgType, FLOAT2FIXED(sc.Float)); } //==========================================================================