mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-04-05 01:11:25 +00:00
Clean up behaviors properly when moving levels
Also adds support for foreach loops with the behavior iterator.
This commit is contained in:
parent
ad87477650
commit
1e05bb2a55
6 changed files with 55 additions and 2 deletions
|
@ -1607,6 +1607,7 @@ void FLevelLocals::StartTravel ()
|
|||
if (Players[i]->health > 0)
|
||||
{
|
||||
pawn->UnlinkFromWorld (nullptr);
|
||||
pawn->UnlinkBehaviorsFromLevel();
|
||||
int tid = pawn->tid; // Save TID
|
||||
pawn->SetTID(0);
|
||||
pawn->tid = tid; // Restore TID (but no longer linked into the hash chain)
|
||||
|
@ -1617,6 +1618,7 @@ void FLevelLocals::StartTravel ()
|
|||
{
|
||||
inv->ChangeStatNum (STAT_TRAVELLING);
|
||||
inv->UnlinkFromWorld (nullptr);
|
||||
inv->UnlinkBehaviorsFromLevel();
|
||||
inv->DeleteAttachedLights();
|
||||
}
|
||||
}
|
||||
|
@ -1720,6 +1722,7 @@ int FLevelLocals::FinishTravel ()
|
|||
pawndup->Destroy();
|
||||
}
|
||||
pawn->LinkToWorld (nullptr);
|
||||
pawn->LinkBehaviorsToLevel();
|
||||
pawn->ClearInterpolation();
|
||||
pawn->ClearFOVInterpolation();
|
||||
const int tid = pawn->tid; // Save TID (actor isn't linked into the hash chain yet)
|
||||
|
@ -1733,6 +1736,7 @@ int FLevelLocals::FinishTravel ()
|
|||
inv->ChangeStatNum (STAT_INVENTORY);
|
||||
inv->LinkToWorld (nullptr);
|
||||
P_FindFloorCeiling(inv, FFCF_ONLYSPAWNPOS);
|
||||
inv->LinkBehaviorsToLevel();
|
||||
|
||||
IFVIRTUALPTRNAME(inv, NAME_Inventory, Travelled)
|
||||
{
|
||||
|
|
|
@ -453,6 +453,7 @@ xx(Playermenu)
|
|||
|
||||
// more stuff
|
||||
xx(Behavior)
|
||||
xx(BehaviorIterator)
|
||||
xx(ColorSet)
|
||||
xx(NeverSwitchOnPickup)
|
||||
xx(MoveBob)
|
||||
|
|
|
@ -380,6 +380,7 @@ void FLevelLocals::ClearLevelData(bool fullgc)
|
|||
aabbTree = nullptr;
|
||||
levelMesh = nullptr;
|
||||
VisualThinkerHead = nullptr;
|
||||
ActorBehaviors.Clear();
|
||||
if (screen)
|
||||
screen->SetAABBTree(nullptr);
|
||||
}
|
||||
|
|
|
@ -1458,6 +1458,9 @@ public:
|
|||
void TickBehaviors();
|
||||
void MoveBehaviors(AActor& from);
|
||||
void ClearBehaviors();
|
||||
// Internal only, mostly for traveling.
|
||||
void UnlinkBehaviorsFromLevel();
|
||||
void LinkBehaviorsToLevel();
|
||||
|
||||
bool HasSpecialDeathStates () const;
|
||||
|
||||
|
|
|
@ -716,6 +716,44 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearBehaviors, ClearBehaviors)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void AActor::UnlinkBehaviorsFromLevel()
|
||||
{
|
||||
TArray<FName> toRemove = {};
|
||||
|
||||
TMap<FName, DBehavior*>::Iterator it = { Behaviors };
|
||||
TMap<FName, DBehavior*>::Pair* pair = nullptr;
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
auto b = pair->Value;
|
||||
if (b == nullptr || (b->ObjectFlags & OF_EuthanizeMe))
|
||||
toRemove.Push(pair->Key);
|
||||
else
|
||||
b->Level->RemoveActorBehavior(*b);
|
||||
}
|
||||
|
||||
for (auto& type : toRemove)
|
||||
RemoveBehavior(*PClass::FindClass(type));
|
||||
}
|
||||
|
||||
void AActor::LinkBehaviorsToLevel()
|
||||
{
|
||||
TArray<FName> toRemove = {};
|
||||
|
||||
TMap<FName, DBehavior*>::Iterator it = { Behaviors };
|
||||
TMap<FName, DBehavior*>::Pair* pair = nullptr;
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
auto b = pair->Value;
|
||||
if (b == nullptr || (b->ObjectFlags & OF_EuthanizeMe))
|
||||
toRemove.Push(pair->Key);
|
||||
else
|
||||
Level->AddActorBehavior(*b);
|
||||
}
|
||||
|
||||
for (auto& type : toRemove)
|
||||
RemoveBehavior(*PClass::FindClass(type));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// AActor::InStateSequence
|
||||
|
|
|
@ -1034,6 +1034,10 @@ FxExpression *FxCastForEachLoop::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
fieldName = "Thinker";
|
||||
}
|
||||
else if (itType->TypeName == NAME_BehaviorIterator)
|
||||
{
|
||||
fieldName = "Behavior";
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "foreach(Type var : it ) - 'it' must be an actor or thinker iterator, but is a %s",Expr->ValueType->DescriptiveName());
|
||||
|
@ -1218,6 +1222,7 @@ bool IsGameSpecificForEachLoop(FxForEachLoop * loop)
|
|||
|| ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_BlockThingsIterator
|
||||
|| ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_ActorIterator
|
||||
|| ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_ThinkerIterator
|
||||
|| ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_BehaviorIterator
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -1232,7 +1237,7 @@ FxExpression * ResolveGameSpecificForEachLoop(FxForEachLoop * loop)
|
|||
delete loop;
|
||||
return blockIt;
|
||||
}
|
||||
else if(cname == NAME_ActorIterator || cname == NAME_ThinkerIterator)
|
||||
else if(cname == NAME_ActorIterator || cname == NAME_ThinkerIterator || cname == NAME_BehaviorIterator)
|
||||
{
|
||||
auto castIt = new FxCastForEachLoop(NAME_None, loop->loopVarName, loop->Array, loop->Code, loop->ScriptPosition);
|
||||
loop->Array = loop->Code = nullptr;
|
||||
|
@ -1324,13 +1329,14 @@ bool IsGameSpecificTypedForEachLoop(FxTypedForEachLoop * loop)
|
|||
return (vt->isObjectPointer() && (
|
||||
((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_ActorIterator
|
||||
|| ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_ThinkerIterator
|
||||
|| ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_BehaviorIterator
|
||||
));
|
||||
}
|
||||
|
||||
FxExpression * ResolveGameSpecificTypedForEachLoop(FxTypedForEachLoop * loop)
|
||||
{
|
||||
assert(loop->Expr->ValueType->isObjectPointer());
|
||||
assert(((PObjectPointer*)loop->Expr->ValueType)->PointedClass()->TypeName == NAME_ActorIterator || ((PObjectPointer*)loop->Expr->ValueType)->PointedClass()->TypeName == NAME_ThinkerIterator);
|
||||
assert(((PObjectPointer*)loop->Expr->ValueType)->PointedClass()->TypeName == NAME_ActorIterator || ((PObjectPointer*)loop->Expr->ValueType)->PointedClass()->TypeName == NAME_ThinkerIterator || ((PObjectPointer*)loop->Expr->ValueType)->PointedClass()->TypeName == NAME_BehaviorIterator);
|
||||
|
||||
FxExpression * castIt = new FxCastForEachLoop(loop->className, loop->varName, loop->Expr, loop->Code, loop->ScriptPosition);
|
||||
loop->Expr = loop->Code = nullptr;
|
||||
|
|
Loading…
Reference in a new issue