Replace C4ActionDef with C4PropList

C4Object now stores a pointer to a C4PropList instead of the Name and Number
of a C4ActionDef in the ActMap of the Object's definition.
stable-5.2
Günther Brammer 2009-04-12 14:03:14 +02:00
parent 427a2f2346
commit b9f398b111
21 changed files with 308 additions and 489 deletions

View File

@ -119,14 +119,13 @@ const DWORD C4D_Load_None = 0,
C4D_Load_Bitmap = 2,
C4D_Load_Script = 4,
C4D_Load_Desc = 8,
C4D_Load_ActMap = 16,
C4D_Load_Image = 32,
C4D_Load_Sounds = 64,
C4D_Load_ClonkNames= 128,
C4D_Load_RankNames = 256,
C4D_Load_RankFaces = 512,
C4D_Load_FE = C4D_Load_Image | C4D_Load_Desc,
C4D_Load_RX = C4D_Load_Bitmap | C4D_Load_Script | C4D_Load_ClonkNames | C4D_Load_Desc | C4D_Load_ActMap | C4D_Load_Sounds | C4D_Load_RankNames | C4D_Load_RankFaces,
C4D_Load_RX = C4D_Load_Bitmap | C4D_Load_Script | C4D_Load_ClonkNames | C4D_Load_Desc | C4D_Load_Sounds | C4D_Load_RankNames | C4D_Load_RankFaces,
C4D_Load_Temporary = 1024;
#define C4D_Blit_Normal 0
@ -136,50 +135,6 @@ const DWORD C4D_Load_None = 0,
#define C4DGFXMODE_NEWGFX 1
#define C4DGFXMODE_OLDGFX 2
const int32_t ActIdle=-1;
const int32_t ActHold=-2;
class C4ActionDef
{
public:
C4ActionDef();
public:
char Name[C4D_MaxIDLen+1];
char ProcedureName[C4D_MaxIDLen+1];
int32_t Procedure; // Mapped by C4Def::Load
int32_t Directions;
int32_t FlipDir;
int32_t Length;
int32_t Delay;
int32_t Attach;
char NextActionName[C4D_MaxIDLen+1];
int32_t NextAction; // Mapped by C4Def::Load
char InLiquidAction[C4D_MaxIDLen+1];
char TurnAction[C4D_MaxIDLen+1];
int32_t FacetBase;
C4TargetRect Facet;
int32_t FacetTopFace;
int32_t NoOtherAction;
int32_t Disabled;
int32_t DigFree;
int32_t FacetTargetStretch;
char Sound[C4D_MaxIDLen+1];
int32_t EnergyUsage;
int32_t Reverse;
int32_t Step;
char SStartCall[C4D_MaxIDLen+1];
char SEndCall[C4D_MaxIDLen+1];
char SAbortCall[C4D_MaxIDLen+1];
char SPhaseCall[C4D_MaxIDLen+1];
class C4AulScriptFunc *StartCall;
C4AulScriptFunc *EndCall;
C4AulScriptFunc *AbortCall;
C4AulScriptFunc *PhaseCall;
public:
void Default();
void CompileFunc(StdCompiler *pComp);
};
class C4Def: public C4PropList
{
public:
@ -289,7 +244,6 @@ class C4Def: public C4PropList
HBITMAP Picture;
HBITMAP Image;
#endif
int32_t ActNum; C4ActionDef *ActMap;
char Maker[C4MaxName+1];
char Filename[_MAX_FNAME+1];
int32_t Creation;

View File

@ -78,13 +78,12 @@ class C4SolidMask;
class C4Action
{
public:
C4Action();
~C4Action();
public:
char Name[C4D_MaxIDLen+1];
int32_t Act; // NoSave //
{
public:
C4Action();
~C4Action();
public:
C4PropList * pActionDef;
int32_t Dir;
int32_t DrawDir; // NoSave // - needs to be calculated for old-style objects.txt anyway
int32_t ComDir;
@ -287,8 +286,9 @@ class C4Object: public C4PropList
BOOL Contact(int32_t cnat);
void TargetBounds(int32_t &ctco, int32_t limit_low, int32_t limit_hi, int32_t cnat_low, int32_t cnat_hi);
enum { SAC_StartCall = 1, SAC_EndCall = 2, SAC_AbortCall = 4, };
BOOL SetAction(int32_t iAct, C4Object *pTarget=NULL, C4Object *pTarget2=NULL, int32_t iCalls = SAC_StartCall | SAC_AbortCall, bool fForce = false);
BOOL SetActionByName(const char *szActName, C4Object *pTarget=NULL, C4Object *pTarget2=NULL, int32_t iCalls = SAC_StartCall | SAC_AbortCall, bool fForce = false);
BOOL SetAction(C4PropList * Act, C4Object *pTarget=NULL, C4Object *pTarget2=NULL, int32_t iCalls = SAC_StartCall | SAC_AbortCall, bool fForce = false);
bool SetActionByName(C4String * ActName, C4Object *pTarget=NULL, C4Object *pTarget2=NULL, int32_t iCalls = SAC_StartCall | SAC_AbortCall, bool fForce = false);
bool SetActionByName(const char * szActName, C4Object *pTarget=NULL, C4Object *pTarget2=NULL, int32_t iCalls = SAC_StartCall | SAC_AbortCall, bool fForce = false);
void SetDir(int32_t tdir);
void SetCategory(int32_t Category) { this->Category = Category; Resort(); SetOCF(); }
int32_t GetProcedure();
@ -406,7 +406,7 @@ class C4Object: public C4PropList
&& !(Category & (C4D_StaticBack | C4D_Structure))
&& !Contained
&& ((~Category & C4D_Vehicle) || (OCF & OCF_Grab))
&& (Action.Act<=ActIdle || Def->ActMap[Action.Act].Procedure != DFA_FLOAT)
&& (!Action.pActionDef || Action.pActionDef->GetPropertyInt(P_Procedure) != DFA_FLOAT)
;
}

View File

@ -164,6 +164,38 @@ enum C4PropertyName {
P_Prototype,
P_Name,
P_Collectible,
P_ActMap,
P_Attach,
P_Procedure,
P_Directions,
P_FlipDir,
P_Length,
P_Delay,
P_X,
P_Y,
P_Wdt,
P_Hgt,
P_OffX,
P_OffY,
P_FacetBase,
P_FacetTopFace,
P_FacetTargetStretch,
P_NextAction,
P_Hold,
P_Idle,
P_NoOtherAction,
P_StartCall,
P_EndCall,
P_AbortCall,
P_PhaseCall,
P_Sound,
P_ObjectDisabled,
P_DigFree,
P_EnergyUsage,
P_InLiquidAction,
P_TurnAction,
P_Reverse,
P_Step,
P_LAST };
// There is only one Stringtable in Game.ScriptEngine

View File

@ -32,8 +32,7 @@ C4Action::~C4Action()
void C4Action::Default()
{
Act=ActIdle;
ZeroMem(Name,C4D_MaxIDLen+1);
pActionDef = 0;
Dir=DIR_None;
DrawDir=Dir;
ComDir=COMD_None;
@ -49,7 +48,7 @@ void C4Action::Default()
void C4Action::CompileFunc(StdCompiler *pComp)
{
// Note: Compiled directly into "Object"-categories, so beware of name clashes (see C4Object::CompileFunc)
pComp->Value(mkNamingAdapt( toC4CStr(Name), "Action", "" ));
// FIXME pComp->Value(mkNamingAdapt( toC4CStr(Name), "Action", "" ));
pComp->Value(mkNamingAdapt( Dir, "Dir", DIR_None ));
pComp->Value(mkNamingAdapt( ComDir, "ComDir", COMD_None ));
pComp->Value(mkNamingAdapt( Time, "ActionTime", 0 ));

View File

@ -301,7 +301,7 @@ void C4Command::MoveTo()
}
// Idles can't move to
if (cObj->Action.Act<=ActIdle)
if (!cObj->Action.pActionDef)
{ Finish(); return; }
// Action
@ -1691,10 +1691,9 @@ BOOL C4Command::FlightControl() // Called by DFA_WALK, DFA_FLIGHT
if (!((cObj->OCF & OCF_CrewMember) || cObj->Def->Pathfinder)) return FALSE;
// Not while in a disabled action
if (cObj->Action.Act > ActIdle)
if (cObj->Action.pActionDef)
{
C4ActionDef *actdef = &(cObj->Def->ActMap[cObj->Action.Act]);
if (actdef->Disabled) return FALSE;
if (cObj->Action.pActionDef->GetPropertyInt(P_ObjectDisabled)) return FALSE;
}
// Target angle

View File

@ -65,73 +65,6 @@ const char *ProcedureName[C4D_MaxDFA]={ "WALK",
"PULL"
};
//-------------------------------- C4ActionDef --------------------------------------------
C4ActionDef::C4ActionDef()
{
Default();
}
void C4ActionDef::Default()
{
ZeroMem(this,sizeof(C4ActionDef));
Procedure=DFA_NONE;
NextAction=ActIdle;
Directions=1;
FlipDir=0;
Length=1;
Delay=0;
FacetBase=0;
Step=1;
StartCall=PhaseCall=EndCall=AbortCall=NULL;
}
void C4ActionDef::CompileFunc(StdCompiler *pComp)
{
pComp->Value(mkNamingAdapt(toC4CStr(Name), "Name", "" ));
pComp->Value(mkNamingAdapt(toC4CStr(ProcedureName), "Procedure", "" ));
pComp->Value(mkNamingAdapt(Directions, "Directions", 1 ));
pComp->Value(mkNamingAdapt(FlipDir, "FlipDir", 0 ));
pComp->Value(mkNamingAdapt(Length, "Length", 1 ));
StdBitfieldEntry<int32_t> CNATs[] = {
{ "CNAT_None" ,CNAT_None },
{ "CNAT_Left" ,CNAT_Left },
{ "CNAT_Right" ,CNAT_Right },
{ "CNAT_Top" ,CNAT_Top },
{ "CNAT_Bottom" ,CNAT_Bottom },
{ "CNAT_Center" ,CNAT_Center },
{ "CNAT_MultiAttach" ,CNAT_MultiAttach },
{ "CNAT_NoCollision" ,CNAT_NoCollision },
{ NULL ,0 }
};
pComp->Value(mkNamingAdapt(mkBitfieldAdapt(Attach, CNATs),
"Attach", 0 ));
pComp->Value(mkNamingAdapt(Delay, "Delay", 0 ));
pComp->Value(mkNamingAdapt(Facet, "Facet", TargetRect0 ));
pComp->Value(mkNamingAdapt(FacetBase, "FacetBase", 0 ));
pComp->Value(mkNamingAdapt(FacetTopFace, "FacetTopFace", 0 ));
pComp->Value(mkNamingAdapt(FacetTargetStretch, "FacetTargetStretch", 0 ));
pComp->Value(mkNamingAdapt(toC4CStr(NextActionName), "NextAction", "" ));
pComp->Value(mkNamingAdapt(NoOtherAction, "NoOtherAction", 0 ));
pComp->Value(mkNamingAdapt(toC4CStr(SStartCall), "StartCall", "" ));
pComp->Value(mkNamingAdapt(toC4CStr(SEndCall), "EndCall", "" ));
pComp->Value(mkNamingAdapt(toC4CStr(SAbortCall), "AbortCall", "" ));
pComp->Value(mkNamingAdapt(toC4CStr(SPhaseCall), "PhaseCall", "" ));
pComp->Value(mkNamingAdapt(toC4CStr(Sound), "Sound", "" ));
pComp->Value(mkNamingAdapt(Disabled, "ObjectDisabled", 0 ));
pComp->Value(mkNamingAdapt(DigFree, "DigFree", 0 ));
pComp->Value(mkNamingAdapt(EnergyUsage, "EnergyUsage", 0 ));
pComp->Value(mkNamingAdapt(toC4CStr(InLiquidAction), "InLiquidAction", "" ));
pComp->Value(mkNamingAdapt(toC4CStr(TurnAction), "TurnAction", "" ));
pComp->Value(mkNamingAdapt(Reverse, "Reverse", 0 ));
pComp->Value(mkNamingAdapt(Step, "Step", 1 ));
}
//--------------------------------- C4DefCore ----------------------------------------------
@ -489,8 +422,6 @@ void C4Def::Default()
Picture=NULL;
Image=NULL;
#endif
ActNum=0;
ActMap=NULL;
Next=NULL;
Temporary=FALSE;
Maker[0]=0;
@ -541,10 +472,8 @@ void C4Def::Clear()
#endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (ActMap) delete [] ActMap; ActMap=NULL;
Desc.Clear();
}
}
BOOL C4Def::Load(C4Group &hGroup,
DWORD dwLoadWhat,
@ -676,16 +605,6 @@ BOOL C4Def::Load(C4Group &hGroup,
return FALSE;
#endif
#ifdef C4ENGINE
// Read ActMap
if (dwLoadWhat & C4D_Load_ActMap)
if (!LoadActMap(hGroup))
{
DebugLogF(" Error loading ActMap of %s (%s)", hGroup.GetFullName().getData(), C4IdText(id));
return FALSE;
}
#endif
#ifdef C4ENGINE
// Read script
if (dwLoadWhat & C4D_Load_Script)
@ -812,61 +731,6 @@ BOOL C4Def::Load(C4Group &hGroup,
return TRUE;
}
BOOL C4Def::LoadActMap(C4Group &hGroup)
{
// New format
StdStrBuf Data;
if (hGroup.LoadEntryString(C4CFN_DefActMap, Data))
{
// Get action count (hacky), create buffer
int actnum;
if(!(actnum = SCharCount('[', Data.getData()))
|| !(ActMap = new C4ActionDef [actnum]))
return FALSE;
// Compile
if(!CompileFromBuf_LogWarn<StdCompilerINIRead>(
mkNamingAdapt(mkArrayAdapt(ActMap, actnum), "Action"),
Data,
(hGroup.GetFullName() + DirSep C4CFN_DefActMap).getData()))
return FALSE;
ActNum = actnum;
// Process map
CrossMapActMap();
return TRUE;
}
// No act map in group: okay
return TRUE;
}
void C4Def::CrossMapActMap()
{
int32_t cnt,cnt2;
for (cnt=0; cnt<ActNum; cnt++)
{
// Map standard procedures
ActMap[cnt].Procedure=DFA_NONE;
for (cnt2=0; cnt2<C4D_MaxDFA; cnt2++)
if (SEqual(ActMap[cnt].ProcedureName,ProcedureName[cnt2]))
ActMap[cnt].Procedure=cnt2;
// Map next action
if (ActMap[cnt].NextActionName[0])
{
if (SEqualNoCase(ActMap[cnt].NextActionName,"Hold"))
ActMap[cnt].NextAction=ActHold;
else
for (cnt2=0; cnt2<ActNum; cnt2++)
if (SEqual(ActMap[cnt].NextActionName,ActMap[cnt2].Name))
ActMap[cnt].NextAction=cnt2;
}
// Check act calls
if (SEqualNoCase(ActMap[cnt].SStartCall,"None")) ActMap[cnt].SStartCall[0]=0;
if (SEqualNoCase(ActMap[cnt].SPhaseCall,"None")) ActMap[cnt].SPhaseCall[0]=0;
if (SEqualNoCase(ActMap[cnt].SEndCall,"None")) ActMap[cnt].SEndCall[0]=0;
if (SEqualNoCase(ActMap[cnt].SAbortCall,"None")) ActMap[cnt].SAbortCall[0]=0;
}
}
BOOL C4Def::ColorizeByMaterial(C4MaterialMap &rMats, BYTE bGBM)
{
#ifdef C4ENGINE // - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -621,7 +621,7 @@ void C4GraphicsOverlay::UpdateFacet()
break;
case MODE_Action: // graphics of specified action
{
/*FIXME {
// Find act in ActMap of object
int32_t cnt;
for (cnt=0; cnt<pDef->ActNum; cnt++)
@ -632,7 +632,7 @@ void C4GraphicsOverlay::UpdateFacet()
// doesn't catch any special action parameters (FacetBase, etc.)...
C4ActionDef *pAct = pDef->ActMap+cnt;
fctBlit.Set(pSourceGfx->GetBitmap(), pAct->Facet.x, pAct->Facet.y, pAct->Facet.Wdt, pAct->Facet.Hgt);
}
}*/
break;
case MODE_IngamePicture:

View File

@ -579,8 +579,8 @@ int32_t FnFxFireStart(C4AulContext *ctx, C4Object *pObj, int32_t iNumber, int32_
cobj = 0;
if (!pObj->Def->IncompleteActivity && !pObj->Def->NoBurnDecay)
while (cobj = Game.FindObject(0, 0, 0, 0, 0, OCF_All, 0, pObj, 0, 0, ANY_OWNER, cobj))
if ((cobj->Action.Act > ActIdle) && (cobj->Def->ActMap[cobj->Action.Act].Procedure == DFA_ATTACH))
cobj->SetAction(ActIdle);
if (cobj->Action.pActionDef && (cobj->Action.pActionDef->GetPropertyInt(P_Procedure) == DFA_ATTACH))
cobj->SetAction(0);
// fire caused?
if (!fFireCaused)
{

View File

@ -602,7 +602,7 @@ bool C4FindObjectCategory::IsEnsured()
bool C4FindObjectAction::Check(C4Object *pObj)
{
return SEqual(pObj->Action.Name, szAction);
return SEqual(pObj->Action.pActionDef->GetName(), szAction);
}
bool C4FindObjectActionTarget::Check(C4Object *pObj)

View File

@ -1181,8 +1181,8 @@ void C4Game::BlastObjects(int32_t tx, int32_t ty, int32_t level, C4Object *inobj
{
if (cObj->Category & C4D_Vehicle)
continue;
if (cObj->Action.Act>=0)
if (cObj->Def->ActMap[cObj->Action.Act].Procedure == DFA_FLOAT)
if (cObj->Action.pActionDef)
if (cObj->Action.pActionDef->GetPropertyInt(P_Procedure) == DFA_FLOAT)
continue;
}
if (cObj->Category & C4D_Living)
@ -1285,9 +1285,9 @@ C4Object* C4Game::FindObject(C4ID id,
// Exclude
if (cObj!=pExclude)
// Action
if (!szAction || !szAction[0] || (bFindActIdle && cObj->Action.Act<=ActIdle) || ((cObj->Action.Act>ActIdle) && SEqual(szAction,cObj->Def->ActMap[cObj->Action.Act].Name)) )
if (!szAction || !szAction[0] || (bFindActIdle && !cObj->Action.pActionDef) || (cObj->Action.pActionDef && SEqual(szAction,cObj->Action.pActionDef->GetName())) )
// ActionTarget
if(!pActionTarget || ((cObj->Action.Act>ActIdle) && ((cObj->Action.Target==pActionTarget) || (cObj->Action.Target2==pActionTarget)) ))
if(!pActionTarget || (cObj->Action.pActionDef && ((cObj->Action.Target==pActionTarget) || (cObj->Action.Target2==pActionTarget)) ))
// Container
if ( !pContainer || (cObj->Contained == pContainer) || ((reinterpret_cast<long>(pContainer)==NO_CONTAINER) && !cObj->Contained) || ((reinterpret_cast<long>(pContainer)==ANY_CONTAINER) && cObj->Contained) )
// Owner
@ -1439,9 +1439,9 @@ int32_t C4Game::ObjectCount(C4ID id,
// Exclude
if (cObj!=pExclude)
// Action
if (!szAction || !szAction[0] || (bFindActIdle && cObj->Action.Act<=ActIdle) || ((cObj->Action.Act>ActIdle) && SEqual(szAction,cObj->Def->ActMap[cObj->Action.Act].Name)) )
if (!szAction || !szAction[0] || (bFindActIdle && !cObj->Action.pActionDef) || (cObj->Action.pActionDef && SEqual(szAction,cObj->Action.pActionDef->GetName())) )
// ActionTarget
if (!pActionTarget || ((cObj->Action.Act>ActIdle) && ((cObj->Action.Target==pActionTarget) || (cObj->Action.Target2==pActionTarget)) ))
if(!pActionTarget || (cObj->Action.pActionDef && ((cObj->Action.Target==pActionTarget) || (cObj->Action.Target2==pActionTarget)) ))
// Container
if ( !pContainer || (cObj->Contained == pContainer) || ((reinterpret_cast<long>(pContainer)==NO_CONTAINER) && !cObj->Contained) || ((reinterpret_cast<long>(pContainer)==ANY_CONTAINER) && cObj->Contained) )
// Owner

View File

@ -170,7 +170,7 @@ void C4GameObjects::CrossCheck() // Every Tick1 by ExecObjects
iHitEnergy = Max<int32_t>(iHitEnergy/3, !!iHitEnergy); // hit energy reduced to 1/3rd, but do not drop to zero because of this division
obj1->DoEnergy(-iHitEnergy/5, false, C4FxCall_EngObjHit, obj2->Controller);
int tmass=Max<int32_t>(obj1->Mass,50);
if (!Tick3 || (obj1->Action.Act>=0 && obj1->Def->ActMap[obj1->Action.Act].Procedure != DFA_FLIGHT))
if (!Tick3 || (obj1->Action.pActionDef && obj1->Action.pActionDef->GetPropertyInt(P_Procedure) != DFA_FLIGHT))
obj1->Fling(obj2->xdir*50/tmass,-Abs(obj2->ydir/2)*50/tmass, false);
obj1->Call(PSF_CatchBlow,&C4AulParSet(C4VInt(-iHitEnergy/5),
C4VObj(obj2)));

View File

@ -57,7 +57,7 @@ void FrameDecoration::Clear()
bool FrameDecoration::SetFacetByAction(C4Def *pOfDef, C4TargetFacet &rfctTarget, const char *szFacetName)
{
// get action
StdStrBuf sActName;
/*FIXME StdStrBuf sActName;
sActName.Format("FrameDeco%s", szFacetName);
int cnt; C4ActionDef *pAct = pOfDef->ActMap;
for (cnt=pOfDef->ActNum; cnt; --cnt,++pAct)
@ -66,7 +66,7 @@ bool FrameDecoration::SetFacetByAction(C4Def *pOfDef, C4TargetFacet &rfctTarget,
if (!cnt) return false;
// set facet by it
rfctTarget.Set(pOfDef->Graphics.GetBitmap(), pAct->Facet.x, pAct->Facet.y, pAct->Facet.Wdt, pAct->Facet.Hgt, pAct->Facet.tx, pAct->Facet.ty);
return true;
*/ return true;
}
bool FrameDecoration::SetByDef(C4ID idSourceDef)

View File

@ -169,7 +169,7 @@ void C4Object::SideBounds(int32_t &ctcox)
{
// layer bounds
if (pLayer) if (pLayer->Def->BorderBound & C4D_Border_Layer)
if (Action.Act<=ActIdle || Def->ActMap[Action.Act].Procedure != DFA_ATTACH)
if (!Action.pActionDef || Action.pActionDef->GetPropertyInt(P_Procedure) != DFA_ATTACH)
if (Category & C4D_StaticBack)
TargetBounds(ctcox,pLayer->GetX()+pLayer->Shape.GetX(),pLayer->GetX()+pLayer->Shape.GetX()+pLayer->Shape.Wdt,CNAT_Left,CNAT_Right);
else
@ -183,7 +183,7 @@ void C4Object::VerticalBounds(int32_t &ctcoy)
{
// layer bounds
if (pLayer) if (pLayer->Def->BorderBound & C4D_Border_Layer)
if (Action.Act<=ActIdle || Def->ActMap[Action.Act].Procedure != DFA_ATTACH)
if (!Action.pActionDef || Action.pActionDef->GetPropertyInt(P_Procedure) != DFA_ATTACH)
if (Category & C4D_StaticBack)
TargetBounds(ctcoy,pLayer->GetY()+pLayer->Shape.GetY(),pLayer->GetY()+pLayer->Shape.GetY()+pLayer->Shape.Hgt,CNAT_Top,CNAT_Bottom);
else
@ -203,11 +203,11 @@ void C4Object::DoMovement()
// Restrictions
if (Def->NoHorizontalMove) xdir=0;
// Dig free target area
if (Action.Act>ActIdle)
if (Def->ActMap[Action.Act].DigFree)
if (Action.pActionDef)
if (Action.pActionDef->GetPropertyInt(P_DigFree))
{
// Shape size square
if (Def->ActMap[Action.Act].DigFree==1)
if (Action.pActionDef->GetPropertyInt(P_DigFree)==1)
{
ctcox=fixtoi(fix_x+xdir); ctcoy=fixtoi(fix_y+ydir);
Game.Landscape.DigFreeRect(ctcox+Shape.GetX(),ctcoy+Shape.GetY(),Shape.Wdt,Shape.Hgt,Action.Data,this);
@ -216,7 +216,7 @@ void C4Object::DoMovement()
else
{
ctcox=fixtoi(fix_x+xdir); ctcoy=fixtoi(fix_y+ydir);
int32_t rad = Def->ActMap[Action.Act].DigFree;
int32_t rad = Action.pActionDef->GetPropertyInt(P_DigFree);
if (Con<FullCon) rad = rad*6*Con/5/FullCon;
Game.Landscape.DigFree(ctcox,ctcoy-1,rad,Action.Data,this);
}
@ -540,7 +540,7 @@ BOOL C4Object::ExecMovement() // Every Tick1 by Execute
if ((!Inside<int32_t>(GetX(),0,GBackWdt) && !(Def->BorderBound & C4D_Border_Sides)) || (GetY()>GBackHgt && !(Def->BorderBound & C4D_Border_Bottom)))
// Never remove attached objects: If they are truly outside landscape, their target will be removed,
// and the attached objects follow one frame later
if (Action.Act<0 || !Action.Target || Def->ActMap[Action.Act].Procedure != DFA_ATTACH)
if (!Action.pActionDef || !Action.Target || Action.pActionDef->GetPropertyInt(P_Procedure) != DFA_ATTACH)
{
bool fRemove = true;
// never remove HUD objects

View File

@ -273,8 +273,8 @@ void C4Object::AssignRemoval(BOOL fExitContents)
if (FrontParticles) FrontParticles.Clear();
if (BackParticles) BackParticles.Clear();
// Action idle
SetAction(ActIdle);
// Object system operation
SetAction(0);
// Object system operation
if (Status == C4OS_INACTIVE)
{
// object was inactive: activate first, then delete
@ -408,9 +408,9 @@ void C4Object::UpdateFlipDir()
{
int32_t iFlipDir;
// We're active
if (Action.Act > ActIdle)
if (Action.pActionDef)
// Get flipdir value from action
if (iFlipDir = Def->ActMap[Action.Act].FlipDir)
if (iFlipDir = Action.pActionDef->GetPropertyInt(P_FlipDir))
// Action dir is in flipdir range
if (Action.Dir >= iFlipDir)
{
@ -500,7 +500,7 @@ void C4Object::DrawActionFace(C4TargetFacet &cgo, float offX, float offY)
const float swdt = float(Action.Facet.Wdt);
const float shgt = float(Action.Facet.Hgt);
int32_t iPhase = Action.Phase;
if (Def->ActMap[Action.Act].Reverse) iPhase = Def->ActMap[Action.Act].Length - 1 - Action.Phase;
if (Action.pActionDef->GetPropertyInt(P_Reverse)) iPhase = Action.pActionDef->GetPropertyInt(P_Length) - 1 - Action.Phase;
// Grow Type Display
float fx = float(Action.Facet.X + swdt * iPhase);
@ -658,7 +658,7 @@ void C4Object::SetOCF()
if ((OCF & OCF_FullCon) || Def->IncompleteActivity)
if ((Def->Collection.Wdt>0) && (Def->Collection.Hgt>0))
if (!Def->CollectionLimit || (Contents.ObjectCount()<Def->CollectionLimit) )
if ((Action.Act<=ActIdle) || (!Def->ActMap[Action.Act].Disabled))
if (!Action.pActionDef || (!Action.pActionDef->GetPropertyInt(P_ObjectDisabled)))
if (NoCollectDelay==0)
OCF|=OCF_Collection;
// OCF_Living
@ -669,7 +669,7 @@ void C4Object::SetOCF()
}
// OCF_FightReady
if (OCF & OCF_Alive)
if ((Action.Act<=ActIdle) || (!Def->ActMap[Action.Act].Disabled))
if (!Action.pActionDef || (!Action.pActionDef->GetPropertyInt(P_ObjectDisabled)))
if (!Def->NoFight)
OCF|=OCF_FightReady;
// OCF_LineConstruct
@ -779,12 +779,12 @@ void C4Object::UpdateOCF()
if ((OCF & OCF_FullCon) || Def->IncompleteActivity)
if ((Def->Collection.Wdt>0) && (Def->Collection.Hgt>0))
if (!Def->CollectionLimit || (Contents.ObjectCount()<Def->CollectionLimit) )
if ((Action.Act<=ActIdle) || (!Def->ActMap[Action.Act].Disabled))
if (!Action.pActionDef || (!Action.pActionDef->GetPropertyInt(P_ObjectDisabled)))
if (NoCollectDelay==0)
OCF|=OCF_Collection;
// OCF_FightReady
if (OCF & OCF_Alive)
if ((Action.Act<=ActIdle) || (!Def->ActMap[Action.Act].Disabled))
if (!Action.pActionDef || (!Action.pActionDef->GetPropertyInt(P_ObjectDisabled)))
if (!Def->NoFight)
OCF|=OCF_FightReady;
// OCF_NotContained
@ -1234,9 +1234,9 @@ BOOL C4Object::ChangeDef(C4ID idNew)
C4Object *pContainer=Contained;
// Exit container (no Ejection/Departure)
if (Contained) Exit(0,0,0,Fix0,Fix0,Fix0,FALSE);
// Pre change resets
SetAction(ActIdle);
Action.Act=ActIdle; // Enforce ActIdle because SetAction may have failed due to NoOtherAction
// Pre change resets
SetAction(0);
Action.pActionDef = 0; // Enforce ActIdle because SetAction may have failed due to NoOtherAction
SetDir(0); // will drop any outdated flipdir
if (pSolidMaskData) { pSolidMaskData->Remove(true, false); delete pSolidMaskData; pSolidMaskData=NULL; }
Def->Count--;
@ -1443,11 +1443,11 @@ void C4Object::DoCon(int32_t iChange, BOOL fInitial, bool fNoComponentChange)
// No energy need
NeedEnergy=0;
}
// Decay from full stop action
if (fWasFull && (Con<FullCon))
// Decay from full stop action
if (fWasFull && (Con<FullCon))
if (!Def->IncompleteActivity)
SetAction(ActIdle);
}
SetAction(0);
}
else
// set first position
if (fInitial) UpdatePos();
@ -2191,9 +2191,8 @@ C4Value C4Object::Call(const char *szFunctionCall, C4AulParSet *pPars, bool fPas
BOOL C4Object::SetPhase(int32_t iPhase)
{
if (Action.Act<=ActIdle) return FALSE;
C4ActionDef *actdef=&(Def->ActMap[Action.Act]);
Action.Phase=BoundBy<int32_t>(iPhase,0,actdef->Length);
if (!Action.pActionDef) return FALSE;
Action.Phase=BoundBy<int32_t>(iPhase,0,Action.pActionDef->GetPropertyInt(P_Length));
return TRUE;
}
@ -2219,8 +2218,8 @@ void C4Object::Draw(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDrawMode)
float offX = cgo.X + fixtof(fix_x) - cotx, offY = cgo.Y + fixtof(fix_y) - coty;
BOOL fYStretchObject=FALSE;
if (Action.Act>ActIdle)
if (Def->ActMap[Action.Act].FacetTargetStretch)
if (Action.pActionDef)
if (Action.pActionDef->GetPropertyInt(P_FacetTargetStretch))
fYStretchObject=TRUE;
// Set audibility
@ -2228,7 +2227,7 @@ void C4Object::Draw(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDrawMode)
// Output boundary
if (!fYStretchObject && !eDrawMode)
if (Action.Act>ActIdle && !r && !Def->ActMap[Action.Act].FacetBase && Con<=FullCon)
if (Action.pActionDef && !r && !Action.pActionDef->GetPropertyInt(P_FacetBase) && Con<=FullCon)
{
// active
if ( !Inside<float>(cox+Action.FacetX,1-Action.Facet.Wdt,cgo.Wdt)
@ -2371,7 +2370,7 @@ void C4Object::Draw(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDrawMode)
if (ColorMod || BlitMode) if (!eDrawMode) PrepareDrawing();
// Not active or rotated: BaseFace only
if ((Action.Act<=ActIdle))
if (!Action.pActionDef)
{
DrawFace(cgo, offX, offY);
}
@ -2380,11 +2379,11 @@ void C4Object::Draw(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDrawMode)
else
{
// FacetBase
if (Def->ActMap[Action.Act].FacetBase)
if (Action.pActionDef->GetPropertyInt(P_FacetBase))
DrawFace(cgo, offX, offY, 0, Action.DrawDir);
// Special: stretched action facet
if (Action.Facet.Surface && Def->ActMap[Action.Act].FacetTargetStretch)
if (Action.Facet.Surface && Action.pActionDef->GetPropertyInt(P_FacetTargetStretch))
{
if (Action.Target)
lpDDraw->Blit(Action.Facet.Surface,
@ -2460,10 +2459,10 @@ void C4Object::Draw(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDrawMode)
if (Game.GraphicsSystem.ShowAction) if (eDrawMode!=ODM_BaseOnly)
{
if (Action.Act>ActIdle)
if (Action.pActionDef)
{
StdStrBuf str;
str.Format("%s (%d)",Def->ActMap[Action.Act].Name,Action.Phase);
str.Format("%s (%d)",Action.pActionDef->GetName(),Action.Phase);
int32_t cmwdt,cmhgt; Game.GraphicsResource.FontRegular.GetTextExtent(str.getData(),cmwdt,cmhgt,true);
Application.DDraw->TextOut(str.getData(), Game.GraphicsResource.FontRegular, 1.0, cgo.Surface,cgo.X+cox-Shape.GetX(),cgo.Y+coy-cmhgt,InLiquid ? 0xfa0000FF : CStdDDraw::DEFAULT_MESSAGE_COLOR,ACenter);
}
@ -2547,13 +2546,12 @@ void C4Object::DrawTopFace(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDraw
fctConSign.Wdt, fctConSign.Hgt, TRUE);
}
// FacetTopFace: Override TopFace.GetX()/GetY()
if ((Action.Act>ActIdle) && Def->ActMap[Action.Act].FacetTopFace)
if (Action.pActionDef && Action.pActionDef->GetPropertyInt(P_FacetTopFace))
{
C4ActionDef *actdef = &Def->ActMap[Action.Act];
int32_t iPhase = Action.Phase;
if (actdef->Reverse) iPhase = actdef->Length - 1 - Action.Phase;
TopFace.X = actdef->Facet.x + Def->TopFace.x + actdef->Facet.Wdt * iPhase;
TopFace.Y = actdef->Facet.y + Def->TopFace.y + actdef->Facet.Hgt * Action.DrawDir;
if (Action.pActionDef->GetPropertyInt(P_Reverse)) iPhase = Action.pActionDef->GetPropertyInt(P_Length) - 1 - Action.Phase;
TopFace.X = Action.pActionDef->GetPropertyInt(P_X) + Def->TopFace.x + Action.pActionDef->GetPropertyInt(P_Wdt) * iPhase;
TopFace.Y = Action.pActionDef->GetPropertyInt(P_Y) + Def->TopFace.y + Action.pActionDef->GetPropertyInt(P_Hgt) * Action.DrawDir;
}
// ensure correct color is set
if (GetGraphics()->BitmapClr) GetGraphics()->BitmapClr->SetClr(Color);
@ -2784,12 +2782,12 @@ void C4Object::CompileFunc(StdCompiler *pComp)
int32_t iTime=Action.Time;
int32_t iPhase=Action.Phase;
int32_t iPhaseDelay=Action.PhaseDelay;
if (SetActionByName(Action.Name,0,0,FALSE))
/* FIXME if (SetActionByName(Action.pActionDef->GetName(),0,0,FALSE))
{
Action.Time=iTime;
Action.Phase=iPhase; // No checking for valid phase
Action.PhaseDelay=iPhaseDelay;
}
}*/
// if on fire but no effect is present (old-style savegames), re-incinerate
int32_t iFireNumber;
@ -4021,176 +4019,159 @@ void C4Object::Resort()
// Must not immediately resort - link change/removal would crash Game::ExecObjects
}
BOOL C4Object::SetAction(int32_t iAct, C4Object *pTarget, C4Object *pTarget2, int32_t iCalls, bool fForce)
{
int32_t iLastAction=Action.Act;
BOOL C4Object::SetAction(C4PropList * Act, C4Object *pTarget, C4Object *pTarget2, int32_t iCalls, bool fForce)
{
C4PropList * LastAction = Action.pActionDef;
int32_t iLastPhase=Action.Phase;
C4ActionDef *pAction;
// Def lost actmap: idle (safety)
if (!Def->ActMap) iLastAction = ActIdle;
// No other action
if (iLastAction>ActIdle)
if (Def->ActMap[iLastAction].NoOtherAction && !fForce)
if (iAct!=iLastAction)
return FALSE;
// Invalid action
if (Def && !Inside<int32_t>(iAct,ActIdle,Def->ActNum-1))
return FALSE;
// Stop previous act sound
if (iLastAction>ActIdle)
if (iAct!=iLastAction)
if (Def->ActMap[iLastAction].Sound[0])
StopSoundEffect(Def->ActMap[iLastAction].Sound,this);
// Unfullcon objects no action
if (Con<FullCon)
// No other action
if (LastAction)
if (LastAction->GetPropertyInt(P_NoOtherAction) && !fForce)
if (Act != LastAction)
return FALSE;
// Stop previous act sound
if (LastAction)
if (Act != LastAction)
if (LastAction->GetPropertyStr(P_Sound))
StopSoundEffect(LastAction->GetPropertyStr(P_Sound)->GetCStr(),this);
// Unfullcon objects no action
if (Con<FullCon)
if (!Def->IncompleteActivity)
iAct = ActIdle;
// Reset action time on change
if (iAct!=iLastAction)
Act = 0;
// Reset action time on change
if (Act!=LastAction)
{
Action.Time=0;
// reset action data if procedure is changed
if (((iAct>ActIdle) ? Def->ActMap[iAct].Procedure : DFA_NONE)
!= ((iLastAction>ActIdle) ? Def->ActMap[iLastAction].Procedure : DFA_NONE))
Action.Data=0;
if ((Act ? Act->GetPropertyInt(P_Procedure) : DFA_NONE)
!= (LastAction ? LastAction->GetPropertyInt(P_Procedure) : DFA_NONE))
Action.Data = 0;
}
// Set new action
Action.Act=iAct;
ZeroMem(Action.Name,C4D_MaxIDLen+1);
if (Action.Act>ActIdle) SCopy(Def->ActMap[Action.Act].Name,Action.Name);
Action.Phase=Action.PhaseDelay=0;
// Set new action
Action.pActionDef = Act;
Action.Phase=Action.PhaseDelay=0;
// Set target if specified
if (pTarget) Action.Target=pTarget;
if (pTarget2) Action.Target2=pTarget2;
if (pTarget) Action.Target=pTarget;
if (pTarget2) Action.Target2=pTarget2;
// Set Action Facet
UpdateActionFace();
// update flipdir
if (((iLastAction>ActIdle) ? Def->ActMap[iLastAction].FlipDir : 0)
!= ((iAct >ActIdle) ? Def->ActMap[iAct ].FlipDir : 0)) UpdateFlipDir();
// Start act sound
if (Action.Act>ActIdle)
if (Action.Act!=iLastAction)
if (Def->ActMap[Action.Act].Sound[0])
StartSoundEffect(Def->ActMap[Action.Act].Sound,+1,100,this);
// Reset OCF
SetOCF();
if ((LastAction ? LastAction->GetPropertyInt(P_FlipDir) : 0)
!= (Act ? Act->GetPropertyInt(P_FlipDir) : 0)) UpdateFlipDir();
// Start act sound
if (Action.pActionDef)
if (Action.pActionDef != LastAction)
if (Action.pActionDef->GetPropertyStr(P_Sound))
StartSoundEffect(Action.pActionDef->GetPropertyStr(P_Sound)->GetCStr(),+1,100,this);
// Reset OCF
SetOCF();
// issue calls
// Execute StartCall
// Execute StartCall
if (iCalls & SAC_StartCall)
if (Action.Act>ActIdle)
if (Action.pActionDef)
{
pAction=&(Def->ActMap[Action.Act]);
if (pAction->StartCall)
if (Action.pActionDef->GetPropertyStr(P_StartCall))
{
C4Def *pOldDef = Def;
pAction->StartCall->Exec(this);
Call(Action.pActionDef->GetPropertyStr(P_StartCall)->GetCStr());
// abort exeution if def changed
if (Def != pOldDef || !Status) return TRUE;
}
}
// Execute EndCall
if(iCalls & SAC_EndCall && !fForce)
if(iLastAction > ActIdle)
// Execute EndCall
if (iCalls & SAC_EndCall && !fForce)
if (LastAction)
{
pAction=&(Def->ActMap[iLastAction]);
if (pAction->EndCall)
if (LastAction->GetPropertyStr(P_EndCall))
{
C4Def *pOldDef = Def;
pAction->EndCall->Exec(this);
Call(LastAction->GetPropertyStr(P_EndCall)->GetCStr());
// abort exeution if def changed
if (Def != pOldDef || !Status) return TRUE;
}
}
// Execute AbortCall
if(iCalls & SAC_AbortCall && !fForce)
if(iLastAction > ActIdle)
// Execute AbortCall
if (iCalls & SAC_AbortCall && !fForce)
if (LastAction)
{
pAction=&(Def->ActMap[iLastAction]);
if (pAction->AbortCall)
if (LastAction->GetPropertyStr(P_AbortCall))
{
C4Def *pOldDef = Def;
pAction->AbortCall->Exec(this, &C4AulParSet(C4VInt(iLastPhase)));
Call(LastAction->GetPropertyStr(P_AbortCall)->GetCStr(), &C4AulParSet(C4VInt(iLastPhase)));
// abort exeution if def changed
if (Def != pOldDef || !Status) return TRUE;
}
}
return TRUE;
}
return TRUE;
}
void C4Object::UpdateActionFace()
{
// Default: no action face
Action.Facet.Default();
// Active: get action facet from action definition
if (Action.Act>ActIdle)
{
C4ActionDef *pAction=&(Def->ActMap[Action.Act]);
if (pAction->Facet.Wdt>0)
{
Action.Facet.Set(GetGraphics()->GetBitmap(Color),pAction->Facet.x,pAction->Facet.y,pAction->Facet.Wdt,pAction->Facet.Hgt);
Action.FacetX=pAction->Facet.tx;
Action.FacetY=pAction->Facet.ty;
}
}
if (Action.pActionDef)
{
if (Action.pActionDef->GetPropertyInt(P_Wdt)>0)
{
Action.Facet.Set(GetGraphics()->GetBitmap(Color),
Action.pActionDef->GetPropertyInt(P_X),Action.pActionDef->GetPropertyInt(P_Y),
Action.pActionDef->GetPropertyInt(P_Wdt),Action.pActionDef->GetPropertyInt(P_Hgt));
Action.FacetX=Action.pActionDef->GetPropertyInt(P_OffX);
Action.FacetY=Action.pActionDef->GetPropertyInt(P_OffY);
}
}
}
BOOL C4Object::SetActionByName(const char *szActName,
bool C4Object::SetActionByName(C4String * ActName,
C4Object *pTarget, C4Object *pTarget2,
int32_t iCalls, bool fForce)
{
int32_t cnt;
// Check for ActIdle passed by name
if (SEqual(szActName,"ActIdle") || SEqual(szActName,"Idle"))
return SetAction(ActIdle,0,0,SAC_StartCall | SAC_AbortCall,fForce);
// Find act in ActMap of object
for (cnt=0; cnt<Def->ActNum; cnt++)
if (SEqual(szActName,Def->ActMap[cnt].Name))
return SetAction(cnt,pTarget,pTarget2,iCalls,fForce);
return FALSE;
}
{
int32_t cnt;
// Check for ActIdle passed by name
if (ActName == Strings.P[P_Idle])
return SetAction(0,0,0,iCalls,fForce);
C4Value ActMap; GetProperty(Strings.P[P_ActMap], ActMap);
if (!ActMap.getPropList()) return false;
C4Value Action; ActMap.getPropList()->GetProperty(ActName, Action);
if (!Action.getPropList()) return false;
return SetAction(Action.getPropList(),pTarget,pTarget2,iCalls,fForce);
}
bool C4Object::SetActionByName(const char * szActName,
C4Object *pTarget, C4Object *pTarget2,
int32_t iCalls, bool fForce)
{
C4String * ActName = Strings.RegString(szActName);
ActName->IncRef();
bool r = SetActionByName(ActName);
ActName->DecRef();
return r;
}
void C4Object::SetDir(int32_t iDir)
{
// Not active
if (Action.Act<=ActIdle) return;
if (!Action.pActionDef) return;
// Invalid direction
if (!Inside<int32_t>(iDir,0,Def->ActMap[Action.Act].Directions-1)) return;
if (!Inside<int32_t>(iDir,0,Action.pActionDef->GetPropertyInt(P_Directions)-1)) return;
// Execute turn action
C4ActionDef *pAction=&(Def->ActMap[Action.Act]);
if (iDir != Action.Dir)
if (pAction->TurnAction[0])
{ SetActionByName(pAction->TurnAction); }
if (Action.pActionDef->GetPropertyStr(P_TurnAction))
{ SetActionByName(Action.pActionDef->GetPropertyStr(P_TurnAction)); }
// Set dir
Action.Dir=iDir;
Action.Dir=iDir;
// update by flipdir?
if (Def->ActMap[Action.Act].FlipDir)
if (Action.pActionDef->GetPropertyInt(P_FlipDir))
UpdateFlipDir();
else
Action.DrawDir=iDir;
}
int32_t C4Object::GetProcedure()
{
if (Action.Act<=ActIdle) return DFA_NONE;
return Def->ActMap[Action.Act].Procedure;
}
{
if (!Action.pActionDef) return DFA_NONE;
return Action.pActionDef->GetPropertyInt(P_Procedure);
}
void GrabLost(C4Object *cObj)
{
@ -4210,7 +4191,7 @@ void DoGravity(C4Object *cobj, BOOL fFloatFriction=TRUE);
void C4Object::NoAttachAction()
{
// Active objects
if (Action.Act > ActIdle)
if (Action.pActionDef)
{
int32_t iProcedure = GetProcedure();
// Scaling upwards: corner scale
@ -4250,9 +4231,9 @@ void C4Object::ContactAction()
C4PhysicalInfo *pPhysical=GetPhysical();
// Determine Procedure
if (Action.Act<=ActIdle) return;
int32_t iProcedure=Def->ActMap[Action.Act].Procedure;
int32_t fDisabled=Def->ActMap[Action.Act].Disabled;
if (!Action.pActionDef) return;
int32_t iProcedure=Action.pActionDef->GetPropertyInt(P_Procedure);
int32_t fDisabled=Action.pActionDef->GetPropertyInt(P_ObjectDisabled);
//------------------------------- Hit Bottom ---------------------------------------------
if (t_contact & CNAT_Bottom)
@ -4616,30 +4597,30 @@ void C4Object::ExecAction()
Mobile=1;
}
// Idle objects do natural gravity only
if (Action.Act<=ActIdle)
{
if (Mobile) DoGravity(this);
return;
}
// Idle objects do natural gravity only
if (!Action.pActionDef)
{
if (Mobile) DoGravity(this);
return;
}
// No IncompleteActivity? Reset action
if (!(OCF & OCF_FullCon) && !Def->IncompleteActivity)
{ SetAction(ActIdle); return; }
{ SetAction(0); return; }
// Determine ActDef & Physical Info
C4ActionDef *pAction=&(Def->ActMap[Action.Act]);
C4PhysicalInfo *pPhysical=GetPhysical();
FIXED lLimit;
// Determine ActDef & Physical Info
C4PropList * pAction = Action.pActionDef;
C4PhysicalInfo *pPhysical=GetPhysical();
FIXED lLimit;
FIXED fWalk,fMove;
int32_t smpx,smpy;
int32_t smpx,smpy;
// Energy usage
if (Game.Rules & C4RULE_StructuresNeedEnergy)
if (pAction->EnergyUsage)
if (pAction->EnergyUsage <= Energy )
if (pAction->GetPropertyInt(P_EnergyUsage))
if (pAction->GetPropertyInt(P_EnergyUsage) <= Energy )
{
Energy -= pAction->EnergyUsage;
Energy -= pAction->GetPropertyInt(P_EnergyUsage);
// No general DoEnergy-Process
NeedEnergy=0;
}
@ -4647,34 +4628,34 @@ void C4Object::ExecAction()
else
{
NeedEnergy=1;
if (Mobile) DoGravity(this);
if (Mobile) DoGravity(this);
return;
}
// Action time advance
Action.Time++;
// InLiquidAction check
if (InLiquid)
if (pAction->InLiquidAction[0])
{ SetActionByName(pAction->InLiquidAction); return; }
Action.Time++;
// InLiquidAction check
if (InLiquid)
if (pAction->GetPropertyStr(P_InLiquidAction))
{ SetActionByName(pAction->GetPropertyStr(P_InLiquidAction)); return; }
// assign extra action attachment (CNAT_MultiAttach)
// regular attachment values cannot be set for backwards compatibility reasons
// this parameter had always been ignored for actions using an internal procedure,
// but is for some obscure reasons set in the KneelDown-actions of the golems
Action.t_attach |= (pAction->Attach & CNAT_MultiAttach);
Action.t_attach |= (pAction->GetPropertyInt(P_Attach) & CNAT_MultiAttach);
// if an object is in controllable state, so it can be assumed that if it dies later because of NO_OWNER's cause,
// it has been its own fault and not the fault of the last one who threw a flint on it
// do not reset for burning objects to make sure the killer is set correctly if they fall out of the map while burning
if (!pAction->Disabled && pAction->Procedure != DFA_FLIGHT && !OnFire)
if (!pAction->GetPropertyInt(P_ObjectDisabled) && pAction->GetPropertyInt(P_Procedure) != DFA_FLIGHT && !OnFire)
LastEnergyLossCausePlayer = NO_OWNER;
// Handle Default Action Procedure: evaluates Procedure and Action.ComDir
// Update xdir,ydir,Action.Dir,attachment,iPhaseAdvance
switch (pAction->Procedure)
{
// Handle Default Action Procedure: evaluates Procedure and Action.ComDir
// Update xdir,ydir,Action.Dir,attachment,iPhaseAdvance
switch (pAction->GetPropertyInt(P_Procedure))
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
case DFA_WALK:
lLimit=ValByPhysical(280, pPhysical->Walk);
@ -5135,7 +5116,7 @@ void C4Object::ExecAction()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
case DFA_LIFT:
// Valid check
if (!Action.Target) { SetAction(ActIdle); return; }
if (!Action.Target) { SetAction(0); return; }
// Target lifting force
lftspeed=itofix(2); tydir=0;
switch (Action.ComDir)
@ -5146,7 +5127,7 @@ void C4Object::ExecAction()
}
// Lift object
if (!Action.Target->Lift(tydir,FIXED100(50)))
{ SetAction(ActIdle); return; }
{ SetAction(0); return; }
// Check LiftTop
if (Def->LiftTop)
if (Action.Target->GetY()<=(GetY()+Def->LiftTop))
@ -5187,7 +5168,7 @@ void C4Object::ExecAction()
{
if (Status)
{
SetAction(ActIdle);
SetAction(0);
Call(PSF_AttachTargetLost);
}
return;
@ -5196,7 +5177,7 @@ void C4Object::ExecAction()
// Target incomplete and no incomplete activity
if (!(Action.Target->OCF & OCF_FullCon))
if (!Action.Target->Def->IncompleteActivity)
{ SetAction(ActIdle); return; }
{ SetAction(0); return; }
// Force containment
if (Action.Target->Contained!=Contained)
@ -5292,11 +5273,11 @@ void C4Object::ExecAction()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
default:
// Attach
if (pAction->Attach)
if (pAction->GetPropertyInt(P_Attach))
{
Action.t_attach|=pAction->Attach;
xdir=ydir=0;
Mobile=1;
Action.t_attach |= pAction->GetPropertyInt(P_Attach);
xdir = ydir = 0;
Mobile = 1;
}
// Free gravity
else
@ -5305,35 +5286,36 @@ void C4Object::ExecAction()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
// Phase Advance (zero delay means no phase advance)
if (pAction->Delay)
{
// Phase Advance (zero delay means no phase advance)
if (pAction->GetPropertyInt(P_Delay))
{
Action.PhaseDelay+=iPhaseAdvance;
if (Action.PhaseDelay>=pAction->Delay)
if (Action.PhaseDelay >= pAction->GetPropertyInt(P_Delay))
{
// Advance Phase
Action.PhaseDelay=0;
Action.Phase += pAction->Step;
Action.Phase += pAction->GetPropertyInt(P_Step);
// Phase call
if (pAction->PhaseCall)
if (pAction->GetPropertyStr(P_PhaseCall))
{
pAction->PhaseCall->Exec(this);
Call(pAction->GetPropertyStr(P_PhaseCall)->GetCStr());
}
// Phase end
if (Action.Phase>=pAction->Length)
if (Action.Phase>=pAction->GetPropertyInt(P_Length))
{
// set new action if it's not Hold
if (pAction->NextAction==ActHold)
Action.Phase = pAction->Length-1;
if (pAction->GetPropertyStr(P_NextAction) == Strings.P[P_Hold])
Action.Phase = pAction->GetPropertyInt(P_Length)-1;
else
{
// Set new action
SetAction(pAction->NextAction, NULL, NULL, SAC_StartCall | SAC_EndCall);
SetActionByName(pAction->GetPropertyStr(P_NextAction), NULL, NULL, SAC_StartCall | SAC_EndCall);
}
}
}
}
}
return;
}
return;
}
BOOL C4Object::SetOwner(int32_t iOwner)
@ -5368,7 +5350,7 @@ BOOL C4Object::SetOwner(int32_t iOwner)
// this automatically updates controller
Controller = Owner;
// if this is a flag flying on a base, the base must be updated
if (id == C4ID_Flag) if (SEqual(Action.Name, "FlyBase")) if (Action.Target && Action.Target->Status)
if (id == C4ID_Flag) if (SEqual(Action.pActionDef->GetName(), "FlyBase")) if (Action.Target && Action.Target->Status)
if (Action.Target->Base == iOldOwner)
{
Action.Target->Base = Owner;
@ -5531,9 +5513,9 @@ BOOL C4Object::Collect(C4Object *pObj)
// Special: attached Flag may not be collectable
if (pObj->Def->id==C4ID_Flag)
if (!(Game.Rules & C4RULE_FlagRemoveable))
if (pObj->Action.Act>ActIdle)
if (SEqual(pObj->Def->ActMap[pObj->Action.Act].Name,"FlyBase"))
return FALSE;
if (pObj->Action.pActionDef)
if (SEqual(pObj->Action.pActionDef->GetName(),"FlyBase"))
return FALSE;
// Object enter container
bool fRejectCollect;
if(!pObj->Enter(this, TRUE, false, &fRejectCollect))

View File

@ -658,9 +658,9 @@ BOOL ObjectComDrop(C4Object *cObj, C4Object *pThing)
int32_t tdir=0; int right=0;
bool isHanglingOrSwimming = false;
int32_t iProc = DFA_NONE;
if (cObj->Action.Act >= 0)
if (cObj->Action.pActionDef)
{
iProc = cObj->Def->ActMap[cObj->Action.Act].Procedure;
iProc = cObj->Action.pActionDef->GetPropertyInt(P_Procedure);
if (iProc == DFA_HANGLE || iProc == DFA_SWIM) isHanglingOrSwimming = true;
}
int32_t iOutposReduction = 1; // don't exit object too far forward during jump
@ -698,7 +698,7 @@ BOOL ObjectComBuild(C4Object *cObj, C4Object *pTarget)
{
if (!pTarget) return FALSE;
// Needs to be idle or walking
if (cObj->Action.Act!=ActIdle)
if (cObj->Action.pActionDef)
if (cObj->GetProcedure()!=DFA_WALK)
return FALSE;
return ObjectActionBuild(cObj,pTarget);
@ -771,7 +771,7 @@ BOOL ObjectComPunch(C4Object *cObj, C4Object *pTarget, int32_t punch)
BOOL ObjectComCancelAttach(C4Object *cObj)
{
if (cObj->GetProcedure()==DFA_ATTACH)
return cObj->SetAction(ActIdle);
return cObj->SetAction(0);
return FALSE;
}

View File

@ -514,7 +514,7 @@ int32_t C4ObjectMenu::AddContextFunctions(C4Object *pTarget, bool fCountOnly)
C4FacetSurface fctSymbol;
// ActionContext functions of target's action target (for first target only, because otherwise strange stuff can happen with outdated Target2s...)
if (pTarget->Action.Act > ActIdle)
if (pTarget->Action.pActionDef)
if (cObj = pTarget->Action.Target)
for (iFunction=0; pFunction=cObj->Def->Script.GetSFunc(iFunction, "ActionContext"); iFunction++)
if (!pFunction->OverloadedBy)
@ -554,8 +554,8 @@ int32_t C4ObjectMenu::AddContextFunctions(C4Object *pTarget, bool fCountOnly)
// Script context functions of any objects attached to target (search global list, because attachment objects might be moved just about anywhere...)
for (clnk=Game.Objects.First; clnk && (cObj=clnk->Obj); clnk=clnk->Next)
if (cObj->Status && cObj->Action.Target == pTarget)
if (cObj->Action.Act > ActIdle)
if (cObj->Def->ActMap[cObj->Action.Act].Procedure == DFA_ATTACH)
if (cObj->Action.pActionDef)
if (cObj->Action.pActionDef->GetPropertyInt(P_Procedure) == DFA_ATTACH)
for (iFunction=0; pFunction=cObj->Def->Script.GetSFunc(iFunction, "AttachContext"); iFunction++)
if (!pFunction->OverloadedBy)
if (!pFunction->Condition || !! pFunction->Condition->Exec(cObj, &C4AulParSet(C4VObj(Object), C4VID(pFunction->idImage), C4VObj(pTarget))))

View File

@ -212,11 +212,11 @@ BOOL C4PropertyDlg::Update()
Output.Append(static_cast<const StdStrBuf &>(cobj->Contents.GetNameList(Game.Defs)));
}
// Action
if (cobj->Action.Act!=ActIdle)
if (cobj->Action.pActionDef)
{
Output.Append(LineFeed);
Output.Append(LoadResStr("IDS_CNS_ACTION"));
Output.Append(cobj->Def->ActMap[cobj->Action.Act].Name);
Output.Append(cobj->Action.pActionDef->GetName());
}
// Locals
int cnt; bool fFirstLocal = true;

View File

@ -729,8 +729,8 @@ static bool FnSetBridgeActionData(C4AulContext *cthr, long iBridgeLength, bool f
{
if (!pObj) pObj=cthr->Obj; if (!pObj || !pObj->Status) return FALSE;
// action must be BRIDGE
if (pObj->Action.Act <= ActIdle) return FALSE;
if (pObj->Def->ActMap[pObj->Action.Act].Procedure != DFA_BRIDGE) return FALSE;
if (!pObj->Action.pActionDef) return FALSE;
if (pObj->Action.pActionDef->GetPropertyInt(P_Procedure) != DFA_BRIDGE) return FALSE;
// set data
pObj->Action.SetBridgeData(iBridgeLength, fMoveClonk, fWall, iBridgeMaterial);
return TRUE;
@ -740,10 +740,10 @@ static bool FnSetActionData(C4AulContext *cthr, long iData, C4Object *pObj)
{
if (!pObj) pObj=cthr->Obj; if (!pObj || !pObj->Status) return FALSE;
// bridge: Convert from old style
if ((pObj->Action.Act > ActIdle) && (pObj->Def->ActMap[pObj->Action.Act].Procedure == DFA_BRIDGE))
if (pObj->Action.pActionDef && (pObj->Action.pActionDef->GetPropertyInt(P_Procedure) == DFA_BRIDGE))
return FnSetBridgeActionData(cthr, 0, false, false, iData, pObj);
// attach: check for valid vertex indices
if ((pObj->Action.Act > ActIdle) && (pObj->Def->ActMap[pObj->Action.Act].Procedure == DFA_ATTACH)) // Fixed Action.Act check here... matthes
if (pObj->Action.pActionDef && (pObj->Action.pActionDef->GetPropertyInt(P_Procedure) == DFA_ATTACH)) // Fixed Action.Act check here... matthes
if (((iData&255) >= C4D_MaxVertex) || ((iData>>8) >= C4D_MaxVertex))
return FALSE;
// set data
@ -960,8 +960,8 @@ static C4Value FnPlayerObjectCommand(C4AulContext *cthr, C4Value *pPars)
static C4String *FnGetAction(C4AulContext *cthr, C4Object *pObj)
{
if (!pObj) pObj=cthr->Obj; if (!pObj) return FALSE;
if (pObj->Action.Act<=ActIdle) return String("Idle");
return String(pObj->Def->ActMap[pObj->Action.Act].Name);
if (!pObj->Action.pActionDef) return String("Idle");
return String(pObj->Action.pActionDef->GetName());
}
static C4PropList * FnCreatePropList(C4AulContext *cthr, C4PropList * prototype)
@ -1856,7 +1856,7 @@ static C4Object *FnFindOtherContents(C4AulContext *cthr, C4ID c_id, C4Object *pO
static bool FnActIdle(C4AulContext *cthr, C4Object *pObj)
{
if (!pObj) pObj=cthr->Obj; if (!pObj) return FALSE;
if (pObj->Action.Act==ActIdle) return TRUE;
if (!pObj->Action.pActionDef) return TRUE;
return FALSE;
}
@ -3847,9 +3847,9 @@ static C4String *FnGetProcedure(C4AulContext *cthr, C4Object *pObj)
// local/safety
if (!pObj) pObj=cthr->Obj; if (!pObj) return NULL;
// no action?
if (pObj->Action.Act <= ActIdle) return NULL;
if (!pObj->Action.pActionDef) return NULL;
// get proc
long iProc = pObj->Def->ActMap[pObj->Action.Act].Procedure;
long iProc = pObj->Action.pActionDef->GetPropertyInt(P_Procedure);
// NONE?
if (iProc <= DFA_NONE) return NULL;
// return procedure name
@ -4344,37 +4344,6 @@ static C4Value FnGetObjectInfoCoreVal(C4AulContext* cthr, C4Value* strEntry_C4V,
return GetValByStdCompiler(strEntry, strSection, iEntryNr, mkNamingAdapt(*pObjInfoCore, "ObjectInfo"));
}
static C4Value FnGetActMapVal(C4AulContext* cthr, C4Value* strEntry_C4V, C4Value* strAction_C4V, C4Value* idDef_C4V, C4Value *iEntryNr_C4V)
{
const char *strEntry = FnStringPar(strEntry_C4V->getStr());
const char *strAction = FnStringPar(strAction_C4V->getStr());
C4ID idDef = idDef_C4V->getC4ID();
long iEntryNr = iEntryNr_C4V->getInt();
if(!idDef) if(cthr->Def) idDef = cthr->Def->id;
if(!idDef) return C4Value();
C4Def* pDef = C4Id2Def(idDef);
if(!pDef) return C4Value();
C4ActionDef* pAct = pDef->ActMap;
if(!pAct) return C4Value();
long iAct;
for(iAct = 0; iAct < pDef->ActNum; iAct++, pAct++)
if(SEqual(pAct->Name, strAction))
break;
// not found?
if(iAct >= pDef->ActNum)
return C4Value();
// get value
return GetValByStdCompiler(strEntry, NULL, iEntryNr, *pAct);
}
static C4Value FnGetScenarioVal(C4AulContext* cthr, C4Value* strEntry_C4V, C4Value* strSection_C4V, C4Value *iEntryNr_C4V)
{
const char *strEntry = FnStringPar(strEntry_C4V->getStr());
@ -7264,7 +7233,6 @@ C4ScriptFnDef C4ScriptFnMap[]={
{ "GetDefCoreVal", 1 ,C4V_Any ,{ C4V_String ,C4V_String ,C4V_C4ID ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetDefCoreVal, 0 },
{ "GetActMapVal", 1 ,C4V_Any ,{ C4V_String ,C4V_String ,C4V_C4ID ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetActMapVal, 0 },
{ "GetObjectVal", 1 ,C4V_Any ,{ C4V_String ,C4V_String ,C4V_C4Object,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetObjectVal, 0 },
{ "GetObjectInfoCoreVal", 1 ,C4V_Any ,{ C4V_String ,C4V_String ,C4V_C4Object,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetObjectInfoCoreVal, 0 },
{ "GetScenarioVal", 1 ,C4V_Any ,{ C4V_String ,C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetScenarioVal, 0 },

View File

@ -208,14 +208,6 @@ void C4DefScriptHost::AfterLink()
if (Def)
{
C4AulAccess CallAccess = /*Strict ? AA_PROTECTED : */AA_PRIVATE;
for (int32_t cnt=0; cnt<Def->ActNum; cnt++)
{
C4ActionDef *pad=&Def->ActMap[cnt];
sprintf(WhereStr, "Action %s: StartCall", pad->Name); pad->StartCall = GetSFuncWarn((const char *) &pad->SStartCall, CallAccess, WhereStr);
sprintf(WhereStr, "Action %s: PhaseCall", pad->Name); pad->PhaseCall = GetSFuncWarn((const char *) &pad->SPhaseCall, CallAccess, WhereStr);
sprintf(WhereStr, "Action %s: EndCall" , pad->Name); pad->EndCall = GetSFuncWarn((const char *) &pad->SEndCall, CallAccess, WhereStr);
sprintf(WhereStr, "Action %s: AbortCall", pad->Name); pad->AbortCall = GetSFuncWarn((const char *) &pad->SAbortCall, CallAccess, WhereStr);
}
Def->TimerCall=GetSFuncWarn((const char *) Def->STimerCall, CallAccess, "TimerCall");
}
// Check if there are any Control/Contained/Activation script functions

View File

@ -80,6 +80,38 @@ C4StringTable::C4StringTable()
P[P_Prototype] = RegString("Prototype");
P[P_Name] = RegString("Name");
P[P_Collectible] = RegString("Collectible");
P[P_ActMap] = RegString("ActMap");
P[P_Procedure] = RegString("Procedure");
P[P_Attach] = RegString("Attach");
P[P_Directions] = RegString("Directions");
P[P_FlipDir] = RegString("FlipDir");
P[P_Length] = RegString("Length");
P[P_Delay] = RegString("Delay");
P[P_X] = RegString("X");
P[P_Y] = RegString("Y");
P[P_Wdt] = RegString("Wdt");
P[P_Hgt] = RegString("Hgt");
P[P_OffX] = RegString("OffX");
P[P_OffY] = RegString("OffY");
P[P_FacetBase] = RegString("FacetBase");
P[P_FacetTopFace] = RegString("FacetTopFace");
P[P_FacetTargetStretch] = RegString("FacetTargetStretch");
P[P_NextAction] = RegString("NextAction");
P[P_Hold] = RegString("Hold");
P[P_Idle] = RegString("Idle");
P[P_NoOtherAction] = RegString("NoOtherAction");
P[P_StartCall] = RegString("StartCall");
P[P_EndCall] = RegString("EndCall");
P[P_AbortCall] = RegString("AbortCall");
P[P_PhaseCall] = RegString("PhaseCall");
P[P_Sound] = RegString("Sound");
P[P_ObjectDisabled] = RegString("ObjectDisabled");
P[P_DigFree] = RegString("DigFree");
P[P_EnergyUsage] = RegString("EnergyUsage");
P[P_InLiquidAction] = RegString("InLiquidAction");
P[P_TurnAction] = RegString("TurnAction");
P[P_Reverse] = RegString("Reverse");
P[P_Step] = RegString("Step");
for (unsigned int i = 0; i < P_LAST; ++i) P[i]->IncRef();
}

View File

@ -22,7 +22,6 @@ static const DFA_ATTACH =14;
static const DFA_FIGHT =15;
static const DFA_CONNECT =16;
static const DFA_PULL =17;
static Action;
global func GetActMapVal(string strEntry, string strAction, id idDef, int iEntryNr) {
if (!idDef) idDef = GetID();
@ -30,8 +29,6 @@ global func GetActMapVal(string strEntry, string strAction, id idDef, int iEntry
return GetProperty(strEntry, GetProperty(strAction, idDef));
}
global func CastC4ID(x) { return x; }
// Abgelöst durch SetPosition
global func ForcePosition(object obj, int x, int y) { return SetPosition(x, y, obj); }