diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 394322f4c..6234c1d30 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,6 +1,31 @@ +March 20, 2007 +- Moved the implementation for the Thing_Damage special into another function + so that I can create the ACS function Thing_Damage2. It's exactly the same as + Thing_Damage, except the damage type is specified by name. When I did this, + I noticed that it didn't do anything useful for a TID of 0, so I made it + affect the activator in that case. + +March 19, 2007 +- Added a new SetActorState ACS function: + int SetActorState (int tid, str statename, optional bool exact); + If tid is 0, it affects the script activator, otherwise it affects all the + matching actors. Statename is the name of the state you want to put the + actor in. The final parameter, exact, specifies whether or not partial + state name matches are accepted. If you don't specify it or set it to + false, if you try to do something like: + SetActorState (0, "Foo.Bar"); + And the actor has a Foo state but no Foo.Bar state, it will enter the Foo + state. If you set exact to true: + SetActorState (0, "Foo.Bar", true); + Then the actor must have a Foo.Bar state, or it will not change state at + all, even if it has a Foo state. + The return value for this function is the number of actors that successfully + changed state. Note that you should refrain from using this function to + enter special states such as Death, or unpredictable results could occur. + March 13, 2007 - Fixed: Morphed players did not regain their innate armor when unmorphing. - (Only Hexen has players with innate armor.) + (Only Hexen has players with innate armor, under normal conditions.) March 12, 2007 - Changed the default player.startitem amount from 0 to 1. diff --git a/src/info.cpp b/src/info.cpp index 6e24688bd..ceec71285 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -486,7 +486,7 @@ FState *AActor::FindState (FName label, FName sublabel, bool exact) const FStateLabel *slabel = info->StateList->FindLabel (label); if (slabel != NULL) { - if (slabel->Children != NULL) + if (sublabel != NAME_None && slabel->Children != NULL) { FStateLabel *slabel2 = slabel->Children->FindLabel(sublabel); if (slabel2 != NULL) @@ -494,7 +494,14 @@ FState *AActor::FindState (FName label, FName sublabel, bool exact) const return slabel2->State; } } - if (!exact) return slabel->State; + if (sublabel == NAME_None && slabel->Children != NULL && exact) + { + return NULL; + } + if (!exact) + { + return slabel->State; + } } } return NULL; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index a0d831ad2..4a10d447d 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4990,6 +4990,57 @@ int DLevelScript::RunScript () sp -= 2; break; + case PCD_SETACTORSTATE: + { + const char *statename = FBehavior::StaticLookupString (STACK(2)); + const char *dot; + FName label1, label2; + FState *state; + + dot = strchr (statename, '.'); + if (dot != NULL) + { + label1 = FName(statename, dot - statename, true); + label2 = FName(dot + 1, true); + } + else + { + label1 = FName(statename, true); + } + if (STACK(3) == 0) + { + state = activator->FindState (label1, label2, !!STACK(1)); + if (state != NULL) + { + activator->SetState (state); + STACK(3) = 1; + } + else + { + STACK(3) = 0; + } + } + else + { + FActorIterator iterator (STACK(3)); + AActor *actor; + int count = 0; + + while ( (actor = iterator.Next ()) ) + { + state = actor->FindState (label1, label2, !!STACK(1)); + if (state != NULL) + { + actor->SetState (state); + count++; + } + } + STACK(3) = count; + } + sp -= 2; + } + break; + case PCD_PLAYERCLASS: // [GRB] if (STACK(1) < 0 || STACK(1) >= MAXPLAYERS || !playeringame[STACK(1)]) { @@ -5095,6 +5146,11 @@ int DLevelScript::RunScript () } } } + + case PCD_THINGDAMAGE2: + STACK(3) = P_Thing_Damage (STACK(3), activator, STACK(2), FName(FBehavior::StaticLookupString(STACK(1)))); + sp -= 2; + break; } } diff --git a/src/p_acs.h b/src/p_acs.h index 5f466d26c..ac72de473 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -3,7 +3,7 @@ ** ACS script stuff ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2007 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -539,6 +539,8 @@ public: PCD_GETACTORPITCH, PCD_SETACTORPITCH, PCD_PRINTBIND, + PCD_SETACTORSTATE, + PCD_THINGDAMAGE2, PCODE_COMMAND_COUNT }; diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index d5febfcc1..888400021 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1127,34 +1127,7 @@ FUNC(LS_Thing_Destroy) FUNC(LS_Thing_Damage) // Thing_Damage (tid, amount, MOD) { - FActorIterator iterator (arg0); - AActor *actor; - - actor = iterator.Next (); - while (actor) - { - AActor *next = iterator.Next (); - if (actor->flags & MF_SHOOTABLE) - { - if (arg1 > 0) - { - P_DamageMobj (actor, NULL, it, arg1, MODtoDamageType (arg2)); - } - else if (actor->health < actor->GetDefault()->health) - { - actor->health -= arg1; - if (actor->health > actor->GetDefault()->health) - { - actor->health = actor->GetDefault()->health; - } - if (actor->player != NULL) - { - actor->player->health = actor->health; - } - } - } - actor = next; - } + P_Thing_Damage (arg0, it, arg1, MODtoDamageType (arg2)); return true; } diff --git a/src/p_local.h b/src/p_local.h index 145e28ea3..006b8a166 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -131,6 +131,7 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_na bool leadTarget); bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog); bool P_Thing_Move (int tid, AActor *source, int mapspot, bool fog); +int P_Thing_Damage (int tid, AActor *whofor0, int amount, FName type); // // P_ENEMY diff --git a/src/p_things.cpp b/src/p_things.cpp index d2643be54..012c3dc00 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -375,6 +375,41 @@ nolead: mobj->angle = R_PointToAngle2 (mobj->x, mobj->y, targ->x, targ->y); return rtn != 0; } +int P_Thing_Damage (int tid, AActor *whofor0, int amount, FName type) +{ + FActorIterator iterator (tid); + int count = 0; + AActor *actor; + + actor = (tid == 0 ? whofor0 : iterator.Next()); + while (actor) + { + AActor *next = tid == 0 ? NULL : iterator.Next (); + if (actor->flags & MF_SHOOTABLE) + { + if (amount > 0) + { + P_DamageMobj (actor, NULL, whofor0, amount, type); + } + else if (actor->health < actor->GetDefault()->health) + { + actor->health -= amount; + if (actor->health > actor->GetDefault()->health) + { + actor->health = actor->GetDefault()->health; + } + if (actor->player != NULL) + { + actor->player->health = actor->health; + } + } + count++; + } + actor = next; + } + return count; +} + CCMD (dumpspawnables) { int i;