From 490742cf46d0b6ea1d18f69642941fce6b66cf63 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 23 Mar 2007 22:26:14 +0000 Subject: [PATCH] - 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. - 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. SVN r505 (trunk) --- docs/rh-log.txt | 27 ++++++++++++++++++++++- src/info.cpp | 11 ++++++++-- src/p_acs.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ src/p_acs.h | 4 +++- src/p_lnspec.cpp | 29 +------------------------ src/p_local.h | 1 + src/p_things.cpp | 35 ++++++++++++++++++++++++++++++ 7 files changed, 131 insertions(+), 32 deletions(-) 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;