int C4Effect::CallStop(int reason, bool temporary) { if (!GetCallbackScript()) return Call(P_Stop, &C4AulParSet(reason, temporary)).getInt(); if (pFnStop) return pFnStop->Exec(GetCallbackScript(), &C4AulParSet(Obj(Target), this, reason, temporary)).getInt(); return C4Fx_OK; }
int C4Effect::CallEffect(const char * effect, const C4Value &var1, const C4Value &var2, const C4Value &var3, const C4Value &var4) { if (!GetCallbackScript()) return Call(P_Effect, &C4AulParSet(effect, var1, var2, var3, var4)).getInt(); if (pFnEffect) return pFnEffect->Exec(GetCallbackScript(), &C4AulParSet(effect, Obj(Target), this, var1, var2, var3, var4)).getInt(); return C4Fx_OK; }
int C4Effect::CallTimer(int time) { if (!GetCallbackScript()) return Call(P_Timer, &C4AulParSet(time)).getInt(); if (pFnTimer) return pFnTimer->Exec(GetCallbackScript(), &C4AulParSet(Obj(Target), this, time)).getInt(); return C4Fx_Execute_Kill; }
int C4Effect::CallStart(int temporary, const C4Value &var1, const C4Value &var2, const C4Value &var3, const C4Value &var4) { if (!GetCallbackScript()) return Call(P_Start, &C4AulParSet(temporary, var1, var2, var3, var4)).getInt(); if (pFnStart) return pFnStart->Exec(GetCallbackScript(), &C4AulParSet(Obj(Target), this, temporary, var1, var2, var3, var4)).getInt(); return C4Fx_OK; }
void C4Effect::CallDamage(int32_t & damage, int damagetype, int plr) { if (!GetCallbackScript()) { C4AulFunc *pFn = GetFunc(P_Damage); if (pFn) damage = pFn->Exec(this, &C4AulParSet(damage, damagetype, plr)).getInt(); } else if (pFnDamage) damage = pFnDamage->Exec(GetCallbackScript(), &C4AulParSet(Obj(Target), this, damage, damagetype, plr)).getInt(); }
void C4Effect::Kill() { // active? C4Effect *pLastRemovedEffect=NULL; if (IsActive()) // then temp remove all higher priority effects TempRemoveUpperEffects(false, &pLastRemovedEffect); else // otherwise: temp reactivate before real removal // this happens only if a lower priority effect removes an upper priority effect in its add- or removal-call if (iPriority!=1) CallStart(C4FxCall_TempAddForRemoval, C4Value(), C4Value(), C4Value(), C4Value()); // remove this effect int32_t iPrevPrio = iPriority; SetDead(); if (CallStop(C4FxCall_Normal, false) == C4Fx_Stop_Deny) // effect denied to be removed: recover iPriority = iPrevPrio; // reactivate other effects TempReaddUpperEffects(pLastRemovedEffect); // Update OnFire cache if (Target && WildcardMatch(C4Fx_AnyFire, GetName())) if (!Get(C4Fx_AnyFire)) Target->SetOnFire(false); if (IsDead() && !GetCallbackScript()) Call(P_Destruction, &C4AulParSet(C4FxCall_Normal)); }
C4Value C4Effect::DoCall(C4Object *pObj, const char *szFn, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4, const C4Value &rVal5, const C4Value &rVal6, const C4Value &rVal7) { // def script or global only? C4PropList *p = GetCallbackScript(); // compose function name char fn[C4AUL_MAX_Identifier+1]; sprintf(fn, PSF_FxCustom, GetName(), szFn); return p->Call(fn, &C4AulParSet(C4VObj(pObj), C4VPropList(this), rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7)); }
void C4Effect::AssignCallbackFunctions() { C4PropList *p = GetCallbackScript(); // compose function names and search them char fn[C4AUL_MAX_Identifier+1]; sprintf(fn, PSF_FxStart, GetName()); pFnStart = p->GetFunc(fn); sprintf(fn, PSF_FxStop, GetName()); pFnStop = p->GetFunc(fn); sprintf(fn, PSF_FxTimer, GetName()); pFnTimer = p->GetFunc(fn); sprintf(fn, PSF_FxEffect, GetName()); pFnEffect = p->GetFunc(fn); sprintf(fn, PSF_FxDamage, GetName()); pFnDamage = p->GetFunc(fn); }
C4Effect * C4Effect::Init(C4PropList *pForObj, int32_t iPrio, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4) { Target = pForObj; // ask all effects with higher priority first - except for prio 1 effects, which are considered out of the priority call chain (as per doc) bool fRemoveUpper = (iPrio != 1); // note that apart from denying the creation of this effect, higher priority effects may also remove themselves // or do other things with the effect list // (which does not quite make sense, because the effect might be denied by another effect) // so the priority is assigned after this call, marking this effect dead before it's definitely valid if (fRemoveUpper && pNext) { C4Effect * pEffect2 = pNext->Check(GetName(), iPrio, iInterval, rVal1, rVal2, rVal3, rVal4); if (pEffect2) { // effect denied (iResult = -1), added to an effect (iResult = Number of that effect) // or added to an effect that destroyed itself (iResult = -2) if (pEffect2 != (C4Effect*)C4Fx_Effect_Deny && pEffect2 != (C4Effect*)C4Fx_Effect_Annul) return pEffect2; // effect is still marked dead return 0; } } // init effect // higher-priority effects must be deactivated temporarily, and then reactivated regarding the new effect // higher-level effects should not be inserted during the process of removing or adding a lower-level effect // because that would cause a wrong initialization order // (hardly ever causing trouble, however...) C4Effect *pLastRemovedEffect=NULL; C4AulFunc * pFn; if (!GetCallbackScript()) { Call(P_Construction, &C4AulParSet(rVal1, rVal2, rVal3, rVal4)).getInt(); if (pForObj && !pForObj->Status) return 0; pFn = GetFunc(P_Start); } else pFn = pFnStart; if (fRemoveUpper && pNext && pFn) TempRemoveUpperEffects(false, &pLastRemovedEffect); // bad things may happen if (pForObj && !pForObj->Status) return 0; // this will be invalid! iPriority = iPrio; // validate effect now if (CallStart(0, rVal1, rVal2, rVal3, rVal4) == C4Fx_Start_Deny) // the effect denied to start: assume it hasn't, and mark it dead SetDead(); if (fRemoveUpper && pNext && pFn) TempReaddUpperEffects(pLastRemovedEffect); if (pForObj && !pForObj->Status) return 0; // this will be invalid! // Update OnFire cache if (!IsDead() && pForObj && WildcardMatch(C4Fx_AnyFire, GetName())) pForObj->SetOnFire(true); return this; }
void C4Effect::AssignCallbackFunctions() { C4AulScript *pSrcScript = GetCallbackScript(); // compose function names and search them char fn[C4AUL_MAX_Identifier + 1]; sprintf(fn, PSF_FxStart, Name); pFnStart = pSrcScript->GetFuncRecursive(fn); sprintf(fn, PSF_FxStop, Name); pFnStop = pSrcScript->GetFuncRecursive(fn); sprintf(fn, PSF_FxTimer, Name); pFnTimer = pSrcScript->GetFuncRecursive(fn); sprintf(fn, PSF_FxEffect, Name); pFnEffect = pSrcScript->GetFuncRecursive(fn); sprintf(fn, PSF_FxDamage, Name); pFnDamage = pSrcScript->GetFuncRecursive(fn); }
C4Value C4Effect::DoCall(C4PropList *pObj, const char *szFn, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4, const C4Value &rVal5, const C4Value &rVal6, const C4Value &rVal7) { C4PropList * p = GetCallbackScript(); if (!p) { C4AulFunc * fn = GetFunc(szFn); if (fn) return fn->Exec(this, &C4AulParSet(rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7)); } else { // old variant // compose function name C4AulFunc * fn = p->GetFunc(FormatString(PSF_FxCustom, GetName(), szFn).getData()); if (fn) return fn->Exec(p, &C4AulParSet(Obj(pObj), this, rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7)); } return C4Value(); }
void C4Effect::ClearAll(int32_t iClearFlag) { // simply remove access all effects recursively, and do removal calls // this does not regard lower-level effects being added in the removal calls, // because this could hang the engine with poorly coded effects if (pNext) pNext->ClearAll(iClearFlag); if ((Target && !Target->Status) || IsDead()) return; int32_t iPrevPrio = iPriority; SetDead(); if (CallStop(iClearFlag, false) == C4Fx_Stop_Deny) { // this stop-callback might have deleted the object and then denied its own removal // must not modify self in this case... if (Target && !Target->Status) return; // effect denied to be removed: recover it iPriority = iPrevPrio; } // Update OnFire cache if (Target && WildcardMatch(C4Fx_AnyFire, GetName()) && IsDead()) if (!Get(C4Fx_AnyFire)) Target->SetOnFire(false); if (IsDead() && !GetCallbackScript()) Call(P_Destruction, &C4AulParSet(iClearFlag)); }