Merge branch 'master' into portals2_visual
This commit is contained in:
commit
f3f77a1ba0
303 changed files with 21853 additions and 10014 deletions
227
src/p_acs.cpp
227
src/p_acs.cpp
|
|
@ -76,6 +76,8 @@
|
|||
#include "farchive.h"
|
||||
#include "decallib.h"
|
||||
#include "portal.h"
|
||||
#include "p_terrain.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "g_shared/a_pickups.h"
|
||||
|
||||
|
|
@ -133,6 +135,16 @@ enum
|
|||
ARMORINFO_ACTUALSAVEAMOUNT,
|
||||
};
|
||||
|
||||
// PickActor
|
||||
// [JP] I've renamed these flags to something else to avoid confusion with the other PAF_ flags
|
||||
enum
|
||||
{
|
||||
// PAF_FORCETID,
|
||||
// PAF_RETURNTID
|
||||
PICKAF_FORCETID = 1,
|
||||
PICKAF_RETURNTID = 2,
|
||||
};
|
||||
|
||||
struct CallReturn
|
||||
{
|
||||
CallReturn(int pc, ScriptFunction *func, FBehavior *module, SDWORD *locals, ACSLocalArrays *arrays, bool discard, unsigned int runaway)
|
||||
|
|
@ -1254,7 +1266,7 @@ static int UseInventory (AActor *activator, const char *type)
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
static int CheckInventory (AActor *activator, const char *type)
|
||||
static int CheckInventory (AActor *activator, const char *type, bool max)
|
||||
{
|
||||
if (activator == NULL || type == NULL)
|
||||
return 0;
|
||||
|
|
@ -1265,11 +1277,26 @@ static int CheckInventory (AActor *activator, const char *type)
|
|||
}
|
||||
else if (stricmp (type, "Health") == 0)
|
||||
{
|
||||
if (max)
|
||||
{
|
||||
if (activator->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
|
||||
return static_cast<APlayerPawn *>(activator)->MaxHealth;
|
||||
else
|
||||
return activator->SpawnHealth();
|
||||
}
|
||||
return activator->health;
|
||||
}
|
||||
|
||||
const PClass *info = PClass::FindClass (type);
|
||||
AInventory *item = activator->FindInventory (info);
|
||||
|
||||
if (max)
|
||||
{
|
||||
if (item)
|
||||
return item->MaxAmount;
|
||||
else
|
||||
return ((AInventory *)GetDefaultByType (info))->MaxAmount;
|
||||
}
|
||||
return item ? item->Amount : 0;
|
||||
}
|
||||
|
||||
|
|
@ -1418,7 +1445,7 @@ FBehavior *FBehavior::StaticLoadModule (int lumpnum, FileReader *fr, int len)
|
|||
else
|
||||
{
|
||||
delete behavior;
|
||||
Printf(TEXTCOLOR_RED "%s: invalid ACS module", Wads.GetLumpFullName(lumpnum));
|
||||
Printf(TEXTCOLOR_RED "%s: invalid ACS module\n", Wads.GetLumpFullName(lumpnum));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1928,11 +1955,14 @@ bool FBehavior::Init(int lumpnum, FileReader * fr, int len)
|
|||
int arraynum = MapVarStore[LittleLong(chunk[2])];
|
||||
if ((unsigned)arraynum < (unsigned)NumArrays)
|
||||
{
|
||||
int initsize = MIN<int> (ArrayStore[arraynum].ArraySize, (LittleLong(chunk[1])-4)/4);
|
||||
// Use unsigned iterator here to avoid issue with GCC 4.9/5.x
|
||||
// optimizer. Might be some undefined behavior in this code,
|
||||
// but I don't know what it is.
|
||||
unsigned int initsize = MIN<unsigned int> (ArrayStore[arraynum].ArraySize, (LittleLong(chunk[1])-4)/4);
|
||||
SDWORD *elems = ArrayStore[arraynum].Elements;
|
||||
for (i = 0; i < initsize; ++i)
|
||||
for (unsigned int j = 0; j < initsize; ++j)
|
||||
{
|
||||
elems[i] = LittleLong(chunk[3+i]);
|
||||
elems[j] = LittleLong(chunk[3+j]);
|
||||
}
|
||||
}
|
||||
chunk = (DWORD *)NextChunk((BYTE *)chunk);
|
||||
|
|
@ -3365,6 +3395,14 @@ int DLevelScript::DoSpawn (int type, fixed_t x, fixed_t y, fixed_t z, int tid, i
|
|||
|
||||
if (info != NULL)
|
||||
{
|
||||
info = info->GetReplacement ();
|
||||
|
||||
if ((GetDefaultByType (info)->flags3 & MF3_ISMONSTER) &&
|
||||
((dmflags & DF_NO_MONSTERS) || (level.flags2 & LEVEL2_NOMONSTERS)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
actor = Spawn (info, x, y, z, ALLOW_REPLACE);
|
||||
if (actor != NULL)
|
||||
{
|
||||
|
|
@ -3404,12 +3442,12 @@ int DLevelScript::DoSpawnSpot (int type, int spot, int tid, int angle, bool forc
|
|||
|
||||
while ( (aspot = iterator.Next ()) )
|
||||
{
|
||||
spawned += DoSpawn (type, aspot->x, aspot->y, aspot->z, tid, angle, force);
|
||||
spawned += DoSpawn (type, aspot->X(), aspot->Y(), aspot->Z(), tid, angle, force);
|
||||
}
|
||||
}
|
||||
else if (activator != NULL)
|
||||
{
|
||||
spawned += DoSpawn (type, activator->x, activator->y, activator->z, tid, angle, force);
|
||||
spawned += DoSpawn (type, activator->X(), activator->Y(), activator->Z(), tid, angle, force);
|
||||
}
|
||||
return spawned;
|
||||
}
|
||||
|
|
@ -3425,12 +3463,12 @@ int DLevelScript::DoSpawnSpotFacing (int type, int spot, int tid, bool force)
|
|||
|
||||
while ( (aspot = iterator.Next ()) )
|
||||
{
|
||||
spawned += DoSpawn (type, aspot->x, aspot->y, aspot->z, tid, aspot->angle >> 24, force);
|
||||
spawned += DoSpawn (type, aspot->X(), aspot->Y(), aspot->Z(), tid, aspot->angle >> 24, force);
|
||||
}
|
||||
}
|
||||
else if (activator != NULL)
|
||||
{
|
||||
spawned += DoSpawn (type, activator->x, activator->y, activator->z, tid, activator->angle >> 24, force);
|
||||
spawned += DoSpawn (type, activator->X(), activator->Y(), activator->Z(), tid, activator->angle >> 24, force);
|
||||
}
|
||||
return spawned;
|
||||
}
|
||||
|
|
@ -3596,7 +3634,7 @@ int DoGetMasterTID (AActor *self)
|
|||
else return 0;
|
||||
}
|
||||
|
||||
static AActor *SingleActorFromTID (int tid, AActor *defactor)
|
||||
AActor *SingleActorFromTID (int tid, AActor *defactor)
|
||||
{
|
||||
if (tid == 0)
|
||||
{
|
||||
|
|
@ -4108,7 +4146,7 @@ bool DLevelScript::DoCheckActorTexture(int tid, AActor *activator, int string, b
|
|||
F3DFloor *ff = sec->e->XFloor.ffloors[i];
|
||||
|
||||
if ((ff->flags & (FF_EXISTS | FF_SOLID)) == (FF_EXISTS | FF_SOLID) &&
|
||||
actor->z >= ff->top.plane->ZatPoint(actor->x, actor->y))
|
||||
actor->Z() >= ff->top.plane->ZatPoint(actor))
|
||||
{ // This floor is beneath our feet.
|
||||
secpic = *ff->top.texture;
|
||||
break;
|
||||
|
|
@ -4121,14 +4159,14 @@ bool DLevelScript::DoCheckActorTexture(int tid, AActor *activator, int string, b
|
|||
}
|
||||
else
|
||||
{
|
||||
fixed_t z = actor->z + actor->height;
|
||||
fixed_t z = actor->Top();
|
||||
// Looking through planes from bottom to top
|
||||
for (i = numff-1; i >= 0; --i)
|
||||
{
|
||||
F3DFloor *ff = sec->e->XFloor.ffloors[i];
|
||||
|
||||
if ((ff->flags & (FF_EXISTS | FF_SOLID)) == (FF_EXISTS | FF_SOLID) &&
|
||||
z <= ff->bottom.plane->ZatPoint(actor->x, actor->y))
|
||||
z <= ff->bottom.plane->ZatPoint(actor))
|
||||
{ // This floor is above our eyes.
|
||||
secpic = *ff->bottom.texture;
|
||||
break;
|
||||
|
|
@ -4423,6 +4461,11 @@ enum EACSFunctions
|
|||
ACSF_ChangeActorRoll,
|
||||
ACSF_GetActorRoll,
|
||||
ACSF_QuakeEx,
|
||||
ACSF_Warp, // 92
|
||||
ACSF_GetMaxInventory,
|
||||
ACSF_SetSectorDamage,
|
||||
ACSF_SetSectorTerrain,
|
||||
|
||||
/* Zandronum's - these must be skipped when we reach 99!
|
||||
-100:ResetMap(0),
|
||||
-101 : PlayerIsSpectator(1),
|
||||
|
|
@ -4686,8 +4729,8 @@ static bool DoSpawnDecal(AActor *actor, const FDecalTemplate *tpl, int flags, an
|
|||
{
|
||||
angle += actor->angle;
|
||||
}
|
||||
return NULL != ShootDecal(tpl, actor, actor->Sector, actor->x, actor->y,
|
||||
actor->z + (actor->height>>1) - actor->floorclip + actor->GetBobOffset() + zofs,
|
||||
return NULL != ShootDecal(tpl, actor, actor->Sector, actor->X(), actor->Y(),
|
||||
actor->Z() + (actor->height>>1) - actor->floorclip + actor->GetBobOffset() + zofs,
|
||||
angle, distance, !!(flags & SDF_PERMANENT));
|
||||
}
|
||||
|
||||
|
|
@ -5295,6 +5338,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
|
|||
ClipRectWidth = argCount > 2 ? args[2] : 0;
|
||||
ClipRectHeight = argCount > 3 ? args[3] : 0;
|
||||
WrapWidth = argCount > 4 ? args[4] : 0;
|
||||
HandleAspect = argCount > 5 ? !!args[5] : true;
|
||||
break;
|
||||
|
||||
case ACSF_SetHUDWrapWidth:
|
||||
|
|
@ -5360,6 +5404,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
|
|||
FName damagetype = argCount > 5 && args[5]? FName(FBehavior::StaticLookupString(args[5])) : NAME_None;
|
||||
fixed_t range = argCount > 6 && args[6]? args[6] : MISSILERANGE;
|
||||
int flags = argCount > 7 && args[7]? args[7] : 0;
|
||||
int pufftid = argCount > 8 && args[8]? args[8] : 0;
|
||||
|
||||
int fhflags = 0;
|
||||
if (flags & FHF_NORANDOMPUFFZ) fhflags |= LAF_NORANDOMPUFFZ;
|
||||
|
|
@ -5367,7 +5412,12 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
|
|||
|
||||
if (args[0] == 0)
|
||||
{
|
||||
P_LineAttack(activator, angle, range, pitch, damage, damagetype, pufftype, fhflags);
|
||||
AActor *puff = P_LineAttack(activator, angle, range, pitch, damage, damagetype, pufftype, fhflags);
|
||||
if (puff != NULL && pufftid != 0)
|
||||
{
|
||||
puff->tid = pufftid;
|
||||
puff->AddToHash();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5376,7 +5426,12 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
|
|||
|
||||
while ((source = it.Next()) != NULL)
|
||||
{
|
||||
P_LineAttack(source, angle, range, pitch, damage, damagetype, pufftype, fhflags);
|
||||
AActor *puff = P_LineAttack(source, angle, range, pitch, damage, damagetype, pufftype, fhflags);
|
||||
if (puff != NULL && pufftid != 0)
|
||||
{
|
||||
puff->tid = pufftid;
|
||||
puff->AddToHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5759,9 +5814,9 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DWORD actorMask = MF_SHOOTABLE;
|
||||
ActorFlags actorMask = MF_SHOOTABLE;
|
||||
if (argCount >= 6) {
|
||||
actorMask = args[5];
|
||||
actorMask = ActorFlags::FromInt(args[5]);
|
||||
}
|
||||
|
||||
DWORD wallMask = ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN;
|
||||
|
|
@ -5769,11 +5824,10 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
|||
wallMask = args[6];
|
||||
}
|
||||
|
||||
bool forceTID = 0;
|
||||
int flags = 0;
|
||||
if (argCount >= 8)
|
||||
{
|
||||
if (args[7] != 0)
|
||||
forceTID = 1;
|
||||
flags = args[7];
|
||||
}
|
||||
|
||||
AActor* pickedActor = P_LinePickActor(actor, args[1] << 16, args[3], args[2] << 16, actorMask, wallMask);
|
||||
|
|
@ -5781,15 +5835,19 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!(forceTID) && (args[4] == 0) && (pickedActor->tid == 0))
|
||||
if (!(flags & PICKAF_FORCETID) && (args[4] == 0) && (pickedActor->tid == 0))
|
||||
return 0;
|
||||
|
||||
if ((pickedActor->tid == 0) || (forceTID))
|
||||
if ((pickedActor->tid == 0) || (flags & PICKAF_FORCETID))
|
||||
{
|
||||
pickedActor->RemoveFromHash();
|
||||
pickedActor->tid = args[4];
|
||||
pickedActor->AddToHash();
|
||||
}
|
||||
if (flags & PICKAF_RETURNTID)
|
||||
{
|
||||
return pickedActor->tid;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
|
@ -5849,11 +5907,94 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
|||
case ACSF_GetActorRoll:
|
||||
actor = SingleActorFromTID(args[0], activator);
|
||||
return actor != NULL? actor->roll >> 16 : 0;
|
||||
|
||||
// [ZK] A_Warp in ACS
|
||||
case ACSF_Warp:
|
||||
{
|
||||
int tid_dest = args[0];
|
||||
fixed_t xofs = args[1];
|
||||
fixed_t yofs = args[2];
|
||||
fixed_t zofs = args[3];
|
||||
angle_t angle = args[4];
|
||||
int flags = args[5];
|
||||
const char *statename = argCount > 6 ? FBehavior::StaticLookupString(args[6]) : "";
|
||||
bool exact = argCount > 7 ? !!args[7] : false;
|
||||
fixed_t heightoffset = argCount > 8 ? args[8] : 0;
|
||||
fixed_t radiusoffset = argCount > 9 ? args[9] : 0;
|
||||
fixed_t pitch = argCount > 10 ? args[10] : 0;
|
||||
|
||||
FState *state = argCount > 6 ? activator->GetClass()->ActorInfo->FindStateByString(statename, exact) : 0;
|
||||
|
||||
AActor *reference;
|
||||
if((flags & WARPF_USEPTR) && tid_dest != AAPTR_DEFAULT)
|
||||
{
|
||||
reference = COPY_AAPTR(activator, tid_dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
reference = SingleActorFromTID(tid_dest, activator);
|
||||
}
|
||||
|
||||
// If there is no actor to warp to, fail.
|
||||
if (!reference)
|
||||
return false;
|
||||
|
||||
if (P_Thing_Warp(activator, reference, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch))
|
||||
{
|
||||
if (state && argCount > 6)
|
||||
{
|
||||
activator->SetState(state);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case ACSF_GetMaxInventory:
|
||||
actor = SingleActorFromTID(args[0], activator);
|
||||
if (actor != NULL)
|
||||
{
|
||||
return CheckInventory(actor, FBehavior::StaticLookupString(args[1]), true);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACSF_SetSectorDamage:
|
||||
if (argCount >= 2)
|
||||
{
|
||||
FSectorTagIterator it(args[0]);
|
||||
int s;
|
||||
while ((s = it.Next()) >= 0)
|
||||
{
|
||||
sector_t *sec = §ors[s];
|
||||
|
||||
sec->damageamount = args[1];
|
||||
sec->damagetype = argCount >= 3 ? FName(FBehavior::StaticLookupString(args[2])) : FName(NAME_None);
|
||||
sec->damageinterval = argCount >= 4 ? clamp(args[3], 1, INT_MAX) : 32;
|
||||
sec->leakydamage = argCount >= 5 ? args[4] : 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ACSF_SetSectorTerrain:
|
||||
if (argCount >= 3)
|
||||
{
|
||||
if (args[1] == sector_t::floor || args[1] == sector_t::ceiling)
|
||||
{
|
||||
int terrain = P_FindTerrain(FBehavior::StaticLookupString(args[2]));
|
||||
FSectorTagIterator it(args[0]);
|
||||
int s;
|
||||
while ((s = it.Next()) >= 0)
|
||||
{
|
||||
sectors[s].terrainnum[args[1]] = terrain;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -5991,6 +6132,7 @@ int DLevelScript::RunScript ()
|
|||
int sp = 0;
|
||||
int *pc = this->pc;
|
||||
ACSFormat fmt = activeBehavior->GetFormat();
|
||||
FBehavior* const savedActiveBehavior = activeBehavior;
|
||||
unsigned int runaway = 0; // used to prevent infinite loops
|
||||
int pcd;
|
||||
FString work;
|
||||
|
|
@ -6024,6 +6166,7 @@ int DLevelScript::RunScript ()
|
|||
{
|
||||
default:
|
||||
Printf ("Unknown P-Code %d in %s\n", pcd, ScriptPresentation(script).GetChars());
|
||||
activeBehavior = savedActiveBehavior;
|
||||
// fall through
|
||||
case PCD_TERMINATE:
|
||||
DPrintf ("%s finished\n", ScriptPresentation(script).GetChars());
|
||||
|
|
@ -7230,9 +7373,9 @@ int DLevelScript::RunScript ()
|
|||
sp--;
|
||||
break;
|
||||
|
||||
case PCD_DROP:
|
||||
case PCD_SETRESULTVALUE:
|
||||
resultValue = STACK(1);
|
||||
case PCD_DROP: //fall through.
|
||||
sp--;
|
||||
break;
|
||||
|
||||
|
|
@ -7787,7 +7930,7 @@ scriptwait:
|
|||
}
|
||||
break;
|
||||
}
|
||||
msg->SetClipRect(ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight);
|
||||
msg->SetClipRect(ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight, HandleAspect);
|
||||
if (WrapWidth != 0)
|
||||
{
|
||||
msg->SetWrapWidth(WrapWidth);
|
||||
|
|
@ -8273,17 +8416,17 @@ scriptwait:
|
|||
break;
|
||||
|
||||
case PCD_CHECKINVENTORY:
|
||||
STACK(1) = CheckInventory (activator, FBehavior::StaticLookupString (STACK(1)));
|
||||
STACK(1) = CheckInventory (activator, FBehavior::StaticLookupString (STACK(1)), false);
|
||||
break;
|
||||
|
||||
case PCD_CHECKACTORINVENTORY:
|
||||
STACK(2) = CheckInventory (SingleActorFromTID(STACK(2), NULL),
|
||||
FBehavior::StaticLookupString (STACK(1)));
|
||||
FBehavior::StaticLookupString (STACK(1)), false);
|
||||
sp--;
|
||||
break;
|
||||
|
||||
case PCD_CHECKINVENTORYDIRECT:
|
||||
PushToStack (CheckInventory (activator, FBehavior::StaticLookupString (TAGSTR(uallong(pc[0])))));
|
||||
PushToStack (CheckInventory (activator, FBehavior::StaticLookupString (TAGSTR(uallong(pc[0]))), false));
|
||||
pc += 1;
|
||||
break;
|
||||
|
||||
|
|
@ -8459,11 +8602,11 @@ scriptwait:
|
|||
}
|
||||
else if (pcd == PCD_GETACTORZ)
|
||||
{
|
||||
STACK(1) = actor->z + actor->GetBobOffset();
|
||||
STACK(1) = actor->Z() + actor->GetBobOffset();
|
||||
}
|
||||
else
|
||||
{
|
||||
STACK(1) = (&actor->x)[pcd - PCD_GETACTORX];
|
||||
STACK(1) = pcd == PCD_GETACTORX ? actor->X() : pcd == PCD_GETACTORY ? actor->Y() : actor->Z();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -8842,7 +8985,22 @@ scriptwait:
|
|||
break;
|
||||
|
||||
case PCD_STRLEN:
|
||||
STACK(1) = SDWORD(strlen(FBehavior::StaticLookupString (STACK(1))));
|
||||
{
|
||||
const char *str = FBehavior::StaticLookupString(STACK(1));
|
||||
if (str != NULL)
|
||||
{
|
||||
STACK(1) = SDWORD(strlen(str));
|
||||
break;
|
||||
}
|
||||
|
||||
static bool StrlenInvalidPrintedAlready = false;
|
||||
if (!StrlenInvalidPrintedAlready)
|
||||
{
|
||||
Printf(PRINT_BOLD, "Warning: ACS function strlen called with invalid string argument.\n");
|
||||
StrlenInvalidPrintedAlready = true;
|
||||
}
|
||||
STACK(1) = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case PCD_GETCVAR:
|
||||
|
|
@ -9302,6 +9460,10 @@ scriptwait:
|
|||
}
|
||||
break;
|
||||
|
||||
case PCD_CONSOLECOMMAND:
|
||||
Printf (TEXTCOLOR_RED GAMENAME " doesn't support execution of console commands from scripts\n");
|
||||
sp -= 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9383,6 +9545,7 @@ DLevelScript::DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr
|
|||
activefont = SmallFont;
|
||||
hudwidth = hudheight = 0;
|
||||
ClipRectLeft = ClipRectTop = ClipRectWidth = ClipRectHeight = WrapWidth = 0;
|
||||
HandleAspect = true;
|
||||
state = SCRIPT_Running;
|
||||
|
||||
// Hexen waited one second before executing any open scripts. I didn't realize
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue