OpenClonk
C4Effect.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 // C4AulFun-based effects assigned to an object
19 /* Also contains some helper functions for various landscape effects */
20 
21 #include "C4Include.h"
22 #include "script/C4Effect.h"
23 
24 #include "game/C4GameScript.h"
25 #include "script/C4Aul.h"
26 
28 {
30  if (!p) return;
31  // compose function names and search them
32  char fn[C4AUL_MAX_Identifier+1];
33  sprintf(fn, PSF_FxStart, GetName()); pFnStart = p->GetFunc(fn);
34  sprintf(fn, PSF_FxStop, GetName()); pFnStop = p->GetFunc(fn);
35  sprintf(fn, PSF_FxTimer, GetName()); pFnTimer = p->GetFunc(fn);
36  sprintf(fn, PSF_FxEffect, GetName()); pFnEffect = p->GetFunc(fn);
37  sprintf(fn, PSF_FxDamage, GetName()); pFnDamage = p->GetFunc(fn);
38 }
39 
41 {
42  return CommandTarget._getPropList();
43 }
44 
45 C4Effect::C4Effect(C4Effect **ppEffectList, C4String *szName, int32_t iPrio, int32_t iTimerInterval, C4PropList *pCmdTarget)
46 {
47  // assign values
48  iPriority = 0; // effect is not yet valid; some callbacks to other effects are done before
49  iInterval = iTimerInterval;
50  iTime = 0;
51  CommandTarget.SetPropList(pCmdTarget);
52  AcquireNumber();
53  Register(ppEffectList, iPrio);
54  // Set name and callback functions
55  SetProperty(P_Name, C4VString(szName));
56 }
57 
58 C4Effect::C4Effect(C4Effect **ppEffectList, C4PropList * prototype, int32_t iPrio, int32_t iTimerInterval):
59  C4PropListNumbered(prototype)
60 {
61  // assign values
62  iPriority = 0; // effect is not yet valid; some callbacks to other effects are done before
63  iInterval = iTimerInterval;
64  iTime = 0;
66  AcquireNumber();
67  Register(ppEffectList, iPrio);
68  SetProperty(P_Name, C4VString(prototype->GetName()));
69 }
70 
71 void C4Effect::Register(C4Effect **ppEffectList, int32_t iPrio)
72 {
73  // get effect target
74  C4Effect *pCheck, *pPrev = *ppEffectList;
75  if (pPrev && Abs(pPrev->iPriority) < iPrio)
76  {
77  while ((pCheck = pPrev->pNext))
78  if (Abs(pCheck->iPriority) >= iPrio) break; else pPrev = pCheck;
79  // insert after previous
80  pNext = pPrev->pNext;
81  pPrev->pNext = this;
82  }
83  else
84  {
85  // insert as first effect
86  pNext = *ppEffectList;
87  *ppEffectList = this;
88  }
89 }
90 
91 C4Effect * C4Effect::New(C4PropList *pForObj, C4Effect **ppEffectList, C4String * szName, int32_t iPrio, int32_t iTimerInterval, C4PropList * pCmdTarget, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4)
92 {
93  C4Effect * pEffect = new C4Effect(ppEffectList, szName, iPrio, iTimerInterval, pCmdTarget);
94  return pEffect->Init(pForObj, iPrio, rVal1, rVal2, rVal3, rVal4);
95 }
96 
97 C4Effect * C4Effect::New(C4PropList *pForObj, C4Effect **ppEffectList, C4PropList * prototype, int32_t iPrio, int32_t iTimerInterval, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4)
98 {
99  C4Effect * pEffect = new C4Effect(ppEffectList, prototype, iPrio, iTimerInterval);
100  return pEffect->Init(pForObj, iPrio, rVal1, rVal2, rVal3, rVal4);
101 }
102 
103 C4Effect * C4Effect::Init(C4PropList *pForObj, int32_t iPrio, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4)
104 {
105  Target = pForObj;
106  // ask all effects with higher priority first - except for prio 1 effects, which are considered out of the priority call chain (as per doc)
107  bool fRemoveUpper = (iPrio != 1);
108  // note that apart from denying the creation of this effect, higher priority effects may also remove themselves
109  // or do other things with the effect list
110  // (which does not quite make sense, because the effect might be denied by another effect)
111  // so the priority is assigned after this call, marking this effect dead before it's definitely valid
112  if (fRemoveUpper && pNext)
113  {
114  C4Effect * pEffect2 = pNext->Check(GetName(), iPrio, iInterval, rVal1, rVal2, rVal3, rVal4);
115  if (pEffect2)
116  {
117  // effect denied (iResult = -1), added to an effect (iResult = Number of that effect)
118  // or added to an effect that destroyed itself (iResult = -2)
119  if (pEffect2 != (C4Effect*)C4Fx_Effect_Deny && pEffect2 != (C4Effect*)C4Fx_Effect_Annul) return pEffect2;
120  // effect is still marked dead
121  return nullptr;
122  }
123  }
124  // init effect
125  // higher-priority effects must be deactivated temporarily, and then reactivated regarding the new effect
126  // higher-level effects should not be inserted during the process of removing or adding a lower-level effect
127  // because that would cause a wrong initialization order
128  // (hardly ever causing trouble, however...)
129  C4Effect *pLastRemovedEffect=nullptr;
130  C4AulFunc * pFn;
131  if (!GetCallbackScript())
132  {
133  Call(P_Construction, &C4AulParSet(rVal1, rVal2, rVal3, rVal4)).getInt();
134  if (pForObj && !pForObj->Status) return nullptr;
135  pFn = GetFunc(P_Start);
136  }
137  else
138  pFn = pFnStart;
139  if (fRemoveUpper && pNext && pFn)
140  TempRemoveUpperEffects(false, &pLastRemovedEffect);
141  // bad things may happen
142  if (pForObj && !pForObj->Status) return nullptr; // this will be invalid!
143  iPriority = iPrio; // validate effect now
144  if (CallStart(0, rVal1, rVal2, rVal3, rVal4) == C4Fx_Start_Deny)
145  // the effect denied to start: assume it hasn't, and mark it dead
146  SetDead();
147  if (fRemoveUpper && pNext && pFn)
148  TempReaddUpperEffects(pLastRemovedEffect);
149  if (pForObj && !pForObj->Status) return nullptr; // this will be invalid!
150  // Update OnFire cache
151  if (!IsDead() && pForObj && WildcardMatch(C4Fx_AnyFire, GetName()))
152  pForObj->SetOnFire(true);
153  return this;
154 }
155 
157 {
158  // defaults
161  pNext = nullptr;
162 }
163 
165 {
166  // del following effects (not recursively)
167  C4Effect *pEffect;
168  while ((pEffect = pNext))
169  {
170  pNext = pEffect->pNext;
171  pEffect->pNext = nullptr;
172  delete pEffect;
173  }
174 }
175 
177 {
178  // denum in all effects
179  C4Effect *pEff = this;
180  do
181  {
182  // command target
183  pEff->CommandTarget.Denumerate(numbers);
184  // assign any callback functions
185  pEff->AssignCallbackFunctions();
186  pEff->C4PropList::Denumerate(numbers);
187  }
188  while ((pEff=pEff->pNext));
189 }
190 
192 {
193  // clear pointers in all effects
194  C4Effect *pEff = this;
195  do
196  // command target lost: effect dead w/o callback
197  if (pEff->CommandTarget.getPropList() == pObj)
198  {
199  pEff->SetDead();
200  pEff->CommandTarget.Set0();
201  }
202  while ((pEff=pEff->pNext));
203 }
204 
206 {
207  iPriority = 0;
208 }
209 
210 C4Effect *C4Effect::Get(const char *szName, int32_t iIndex, int32_t iMaxPriority)
211 {
212  // safety
213  if (!szName) return nullptr;
214  // check all effects
215  C4Effect *pEff = this;
216  do
217  {
218  // skip dead
219  if (pEff->IsDead()) continue;
220  // skip effects with too high priority
221  if (iMaxPriority && pEff->iPriority > iMaxPriority) continue;
222  // wildcard compare name
223  const char *szEffectName = pEff->GetName();
224  if (!SWildcardMatchEx(szEffectName, szName)) continue;
225  // effect name matches
226  // check index
227  if (iIndex--) continue;
228  // effect found
229  return pEff;
230  }
231  while ((pEff=pEff->pNext));
232  // nothing found
233  return nullptr;
234 }
235 
236 int32_t C4Effect::GetCount(const char *szMask, int32_t iMaxPriority)
237 {
238  // count all matching effects
239  int32_t iCnt=0; C4Effect *pEff = this;
240  do if (!pEff->IsDead())
241  if (!szMask || SWildcardMatchEx(pEff->GetName(), szMask))
242  if (!iMaxPriority || pEff->iPriority <= iMaxPriority)
243  ++iCnt;
244  while ((pEff = pEff->pNext));
245  // return count
246  return iCnt;
247 }
248 
249 C4Effect* C4Effect::Check(const char *szCheckEffect, int32_t iPrio, int32_t iTimer, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4)
250 {
251  // priority=1: always OK; no callbacks
252  if (iPrio == 1) return nullptr;
253  // check this and other effects
254  C4Effect *pAddToEffect = nullptr; bool fDoTempCallsForAdd = false;
255  C4Effect *pLastRemovedEffect=nullptr;
256  for (C4Effect *pCheck = this; pCheck; pCheck = pCheck->pNext)
257  {
258  if (!pCheck->IsDead() && pCheck->iPriority >= iPrio)
259  {
260  int32_t iResult = pCheck->CallEffect(szCheckEffect, rVal1, rVal2, rVal3, rVal4);
261  if (iResult == C4Fx_Effect_Deny)
262  // effect denied
263  return (C4Effect*)C4Fx_Effect_Deny;
264  // add to other effect
266  {
267  pAddToEffect = pCheck;
268  fDoTempCallsForAdd = (iResult == C4Fx_Effect_AnnulCalls);
269  }
270  }
271  }
272  // adding to other effect?
273  if (pAddToEffect)
274  {
275  // do temp remove calls if desired
276  if (pAddToEffect->pNext && fDoTempCallsForAdd)
277  pAddToEffect->TempRemoveUpperEffects(false, &pLastRemovedEffect);
278  C4Value Par1 = C4VString(szCheckEffect), Par2 = C4VInt(iTimer), Par8;
279  int32_t iResult = pAddToEffect->DoCall(Target, PSFS_FxAdd, Par1, Par2, rVal1, rVal2, rVal3, rVal4, Par8).getInt();
280  // do temp readd calls if desired
281  if (pAddToEffect->pNext && fDoTempCallsForAdd)
282  pAddToEffect->TempReaddUpperEffects(pLastRemovedEffect);
283  // effect removed by this call?
284  if (iResult == C4Fx_Start_Deny)
285  {
286  pAddToEffect->Kill();
287  return (C4Effect*)C4Fx_Effect_Annul;
288  }
289  else
290  // other effect is the target effect number
291  return pAddToEffect;
292  }
293  // added to no effect and not denied
294  return nullptr;
295 }
296 
297 void C4Effect::Execute(C4Effect **ppEffectList)
298 {
299  // advance all effect timers first; then do execution
300  // this prevents a possible endless loop if timers register into the same effect list with interval 1 while it is being executed
301  for (C4Effect *pEffect = *ppEffectList; pEffect; pEffect = pEffect->pNext)
302  {
303  // ignore dead status; adjusting their time doesn't hurt
304  ++pEffect->iTime;
305  }
306  // get effect list
307  // execute all effects not marked as dead
308  C4Effect *pEffect = *ppEffectList, **ppPrevEffect=ppEffectList;
309  while (pEffect)
310  {
311  // effect dead?
312  if (pEffect->IsDead())
313  {
314  // delete it, then
315  C4Effect *pNextEffect = pEffect->pNext;
316  pEffect->pNext = nullptr;
317  delete pEffect;
318  // next effect
319  *ppPrevEffect = pEffect = pNextEffect;
320  }
321  else
322  {
323  // check timer execution
324  if (pEffect->iInterval && !(pEffect->iTime % pEffect->iInterval) && pEffect->iTime)
325  {
326  if (pEffect->CallTimer(pEffect->iTime) == C4Fx_Execute_Kill)
327  {
328  // safety: this class got deleted!
329  if (pEffect->Target && !pEffect->Target->Status) return;
330  // timer function decided to finish it
331  pEffect->Kill();
332  }
333  // safety: this class got deleted!
334  if (pEffect->Target && !pEffect->Target->Status) return;
335  }
336  // next effect
337  ppPrevEffect = &pEffect->pNext;
338  pEffect = pEffect->pNext;
339  }
340  }
341 }
342 
344 {
345  // active?
346  C4Effect *pLastRemovedEffect=nullptr;
347  if (IsActive())
348  // then temp remove all higher priority effects
349  TempRemoveUpperEffects(false, &pLastRemovedEffect);
350  else
351  // otherwise: temp reactivate before real removal
352  // this happens only if a lower priority effect removes an upper priority effect in its add- or removal-call
354  // remove this effect
355  int32_t iPrevPrio = iPriority; SetDead();
356  if (CallStop(C4FxCall_Normal, false) == C4Fx_Stop_Deny)
357  // effect denied to be removed: recover
358  iPriority = iPrevPrio;
359  // reactivate other effects
360  TempReaddUpperEffects(pLastRemovedEffect);
361  // Update OnFire cache
363  if (!Get(C4Fx_AnyFire))
364  Target->SetOnFire(false);
365  if (IsDead() && !GetCallbackScript())
367 }
368 
369 void C4Effect::ClearAll(int32_t iClearFlag)
370 {
371  // simply remove access all effects recursively, and do removal calls
372  // this does not regard lower-level effects being added in the removal calls,
373  // because this could hang the engine with poorly coded effects
374  if (pNext) pNext->ClearAll(iClearFlag);
375  if ((Target && !Target->Status) || IsDead()) return;
376  int32_t iPrevPrio = iPriority;
377  SetDead();
378  if (CallStop(iClearFlag, false) == C4Fx_Stop_Deny)
379  {
380  // this stop-callback might have deleted the object and then denied its own removal
381  // must not modify self in this case...
382  if (Target && !Target->Status) return;
383  // effect denied to be removed: recover it
384  iPriority = iPrevPrio;
385  }
386  // Update OnFire cache
388  if (!Get(C4Fx_AnyFire))
389  Target->SetOnFire(false);
390  if (IsDead() && !GetCallbackScript())
391  Call(P_Destruction, &C4AulParSet(iClearFlag));
392 }
393 
394 void C4Effect::DoDamage(int32_t &riDamage, int32_t iDamageType, int32_t iCausePlr)
395 {
396  // ask all effects for damage adjustments
397  C4Effect *pEff = this;
398  do
399  {
400  if (!pEff->IsDead())
401  pEff->CallDamage(riDamage, iDamageType, iCausePlr);
402  if (Target && !Target->Status) return;
403  }
404  while ((pEff = pEff->pNext) && riDamage);
405 }
406 
407 static C4Object * Obj(C4PropList * p) { return p ? p->GetObject() : nullptr; }
408 
409 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)
410 {
412  if (!p)
413  {
414  C4AulFunc * fn = GetFunc(szFn);
415  if (fn) return fn->Exec(this, &C4AulParSet(rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7));
416  }
417  else
418  {
419  // old variant
420  // compose function name
421  C4AulFunc * fn = p->GetFunc(FormatString(PSF_FxCustom, GetName(), szFn).getData());
422  if (fn) return fn->Exec(p, &C4AulParSet(Obj(pObj), this, rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7));
423  }
424  return C4Value();
425 }
426 
427 int C4Effect::CallStart(int temporary, const C4Value &var1, const C4Value &var2, const C4Value &var3, const C4Value &var4)
428 {
429  if (!GetCallbackScript())
430  return Call(P_Start, &C4AulParSet(temporary, var1, var2, var3, var4)).getInt();
431  if (pFnStart)
432  return pFnStart->Exec(GetCallbackScript(), &C4AulParSet(Obj(Target), this, temporary, var1, var2, var3, var4)).getInt();
433  return C4Fx_OK;
434 }
435 int C4Effect::CallStop(int reason, bool temporary)
436 {
437  if (!GetCallbackScript())
438  return Call(P_Stop, &C4AulParSet(reason, temporary)).getInt();
439  if (pFnStop)
440  return pFnStop->Exec(GetCallbackScript(), &C4AulParSet(Obj(Target), this, reason, temporary)).getInt();
441  return C4Fx_OK;
442 }
443 int C4Effect::CallTimer(int time)
444 {
445  try
446  {
447  if (!GetCallbackScript())
448  return Call(P_Timer, &C4AulParSet(time), true).getInt();
449  if (pFnTimer)
450  return pFnTimer->Exec(GetCallbackScript(), &C4AulParSet(Obj(Target), this, time), true).getInt();
451  }
452  catch (C4AulError &e)
453  {
454  // Script error: remove the timer.
455  // TODO: The error message is printed after the stack trace. No way around that currently.
457  // => Removing effect { ... }
458  DebugLogF(" Removing %s", C4Value(this).GetDataString(3).getData());
459  }
460  return C4Fx_Execute_Kill;
461 }
462 void C4Effect::CallDamage(int32_t & damage, int damagetype, int plr)
463 {
464  if (!GetCallbackScript())
465  {
466  C4AulFunc *pFn = GetFunc(P_Damage);
467  if (pFn)
468  damage = pFn->Exec(this, &C4AulParSet(damage, damagetype, plr)).getInt();
469  }
470  else if (pFnDamage)
471  damage = pFnDamage->Exec(GetCallbackScript(), &C4AulParSet(Obj(Target), this, damage, damagetype, plr)).getInt();
472 }
473 int C4Effect::CallEffect(const char * effect, const C4Value &var1, const C4Value &var2, const C4Value &var3, const C4Value &var4)
474 {
475  if (!GetCallbackScript())
476  return Call(P_Effect, &C4AulParSet(effect, var1, var2, var3, var4)).getInt();
477  if (pFnEffect)
478  return pFnEffect->Exec(GetCallbackScript(), &C4AulParSet(effect, Obj(Target), this, var1, var2, var3, var4)).getInt();
479  return C4Fx_OK;
480 }
481 
483 {
484  // safety
485  if (!pObj) return;
486  // check all effects for reassignment
487  C4Effect *pCheck = this;
488  while (pCheck)
489  {
490  if (pCheck->GetCallbackScript() == pObj)
491  pCheck->ReAssignCallbackFunctions();
492  pCheck = pCheck->pNext;
493  }
494 }
495 
496 void C4Effect::TempRemoveUpperEffects(bool fTempRemoveThis, C4Effect **ppLastRemovedEffect)
497 {
498  if (Target && !Target->Status) return; // this will be invalid!
499  // priority=1: no callbacks
500  if (iPriority == 1) return;
501  // remove from high to low priority
502  // recursive implementation...
503  C4Effect *pEff = pNext;
504  while (pEff) if (pEff->IsActive()) break; else pEff = pEff->pNext;
505  // temp remove active effects with higher priority
506  if (pEff) pEff->TempRemoveUpperEffects(true, ppLastRemovedEffect);
507  // temp remove this
508  if (fTempRemoveThis)
509  {
510  FlipActive();
511  // Update OnFire cache
513  if (!Get(C4Fx_AnyFire))
514  Target->SetOnFire(false);
515  // temp callbacks only for higher priority effects
516  if (iPriority!=1) CallStop(C4FxCall_Temp, true);
517  if (!*ppLastRemovedEffect) *ppLastRemovedEffect = this;
518  }
519 }
520 
522 {
523  // nothing to do? - this will also happen if TempRemoveUpperEffects did nothing due to priority==1
524  if (!pLastReaddEffect) return;
525  if (Target && !Target->Status) return; // this will be invalid!
526  // simply activate all following, inactive effects
527  for (C4Effect *pEff = pNext; pEff; pEff = pEff->pNext)
528  {
529  if (pEff->IsInactiveAndNotDead())
530  {
531  pEff->FlipActive();
532  if (pEff->iPriority!=1) pEff->CallStart(C4FxCall_Temp, C4Value(), C4Value(), C4Value(), C4Value());
533  if (Target && WildcardMatch(C4Fx_AnyFire, pEff->GetName()))
534  Target->SetOnFire(true);
535  }
536  // done?
537  if (pEff == pLastReaddEffect) break;
538  }
539 }
540 
542 {
543  if (pComp->isDeserializer()) Target = Owner;
544  // read name
545  pComp->Separator(StdCompiler::SEP_START); // '('
546  // read priority
547  pComp->Value(iPriority); pComp->Separator();
548  // read time and intervall
549  pComp->Value(iTime); pComp->Separator();
550  pComp->Value(iInterval); pComp->Separator();
551  // read object number
552  // FIXME: replace with this when savegame compat breaks for other reasons
553  // pComp->Value(mkParAdapt(CommandTarget, numbers));
554  int32_t nptr = 0;
557  pComp->Value(nptr);
558  if (pComp->isDeserializer())
560  pComp->Separator();
561  // read ID
562  if (pComp->isSerializer())
563  {
565  if (p)
566  p->RefCompileFunc(pComp, numbers);
567  else
568  pComp->String(const_cast<char*>("None"), 5, StdCompiler::RCT_ID);
569  }
570  else
571  {
572  StdStrBuf s;
574  // An Object trumps a definition as command target
575  if (!nptr)
576  if (!::ScriptEngine.GetGlobalConstant(s.getData(), &CommandTarget))
578  }
579  pComp->Separator();
580  // proplist
581  C4PropListNumbered::CompileFunc(pComp, numbers);
582  pComp->Separator(StdCompiler::SEP_END); // ')'
583  // is there a next effect?
584  bool fNext = !! pNext;
585  if (pComp->hasNaming())
586  {
587  if (fNext || pComp->isDeserializer())
588  fNext = pComp->Separator();
589  }
590  else
591  pComp->Value(fNext);
592  if (!fNext) return;
593  // read next
594  pComp->Value(mkParAdapt(mkPtrAdaptNoNull(pNext), Owner, numbers));
595  // denumeration and callback assignment will be done later
596 }
597 
599 {
600  if (k >= &Strings.P[0] && k < &Strings.P[P_LAST])
601  {
602  switch(k - &Strings.P[0])
603  {
604  case P_Name:
605  if (!to.getStr() || !*to.getStr()->GetCStr())
606  throw C4AulExecError("effect: Name has to be a nonempty string");
609  return;
610  case P_Priority:
611  throw C4AulExecError("effect: Priority is readonly");
612  case P_Interval: iInterval = to.getInt(); return;
613  case P_CommandTarget:
614  throw C4AulExecError("effect: CommandTarget is readonly");
615  case P_Target:
616  throw C4AulExecError("effect: Target is readonly");
617  case P_Time: iTime = to.getInt(); return;
618  case P_Prototype:
619  throw new C4AulExecError("effect: Prototype is readonly");
620  }
621  }
623 }
624 
626 {
627  if (k >= &Strings.P[0] && k < &Strings.P[P_LAST])
628  {
629  switch(k - &Strings.P[0])
630  {
631  case P_Name:
632  throw C4AulExecError("effect: Name has to be a nonempty string");
633  case P_Priority:
634  throw C4AulExecError("effect: Priority is readonly");
635  case P_Interval: iInterval = 0; return;
636  case P_CommandTarget:
637  throw C4AulExecError("effect: CommandTarget is readonly");
638  case P_Target:
639  throw C4AulExecError("effect: Target is readonly");
640  case P_Time: iTime = 0; return;
641  case P_Prototype:
642  throw new C4AulExecError("effect: Prototype is readonly");
643  }
644  }
646 }
647 
648 bool C4Effect::GetPropertyByS(const C4String *k, C4Value *pResult) const
649 {
650  if (k >= &Strings.P[0] && k < &Strings.P[P_LAST])
651  {
652  switch(k - &Strings.P[0])
653  {
654  case P_Name: return C4PropListNumbered::GetPropertyByS(k, pResult);
655  case P_Priority: *pResult = C4VInt(Abs(iPriority)); return true;
656  case P_Interval: *pResult = C4VInt(iInterval); return true;
657  case P_CommandTarget: *pResult = CommandTarget; return true;
658  case P_Target: *pResult = C4Value(Target); return true;
659  case P_Time: *pResult = C4VInt(iTime); return true;
660  }
661  }
662  return C4PropListNumbered::GetPropertyByS(k, pResult);
663 }
664 
666 {
668  int i;
669  i = a->GetSize();
670  a->SetSize(i + 5);
671  (*a)[i++] = C4VString(&::Strings.P[P_Name]);
672  (*a)[i++] = C4VString(&::Strings.P[P_Priority]);
673  (*a)[i++] = C4VString(&::Strings.P[P_Interval]);
674  (*a)[i++] = C4VString(&::Strings.P[P_CommandTarget]);
675  (*a)[i++] = C4VString(&::Strings.P[P_Target]);
676  (*a)[i++] = C4VString(&::Strings.P[P_Time]);
677  return a;
678 }
#define C4AUL_MAX_Identifier
Definition: C4Aul.h:26
#define s
#define C4FxCall_Normal
Definition: C4Effect.h:42
#define C4Fx_Execute_Kill
Definition: C4Effect.h:36
#define C4Fx_Start_Deny
Definition: C4Effect.h:39
#define C4FxCall_Temp
Definition: C4Effect.h:43
#define C4Fx_Effect_Annul
Definition: C4Effect.h:33
#define C4Fx_Stop_Deny
Definition: C4Effect.h:38
#define C4Fx_Effect_Deny
Definition: C4Effect.h:32
#define C4Fx_OK
Definition: C4Effect.h:30
#define C4Fx_Effect_AnnulCalls
Definition: C4Effect.h:34
#define C4FxCall_TempAddForRemoval
Definition: C4Effect.h:44
#define C4Fx_AnyFire
Definition: C4Effect.h:149
#define PSF_FxEffect
Definition: C4GameScript.h:112
#define PSF_FxCustom
Definition: C4GameScript.h:114
#define PSF_FxStart
Definition: C4GameScript.h:109
#define PSFS_FxAdd
Definition: C4GameScript.h:156
#define PSF_FxTimer
Definition: C4GameScript.h:111
#define PSF_FxDamage
Definition: C4GameScript.h:113
#define PSF_FxStop
Definition: C4GameScript.h:110
C4AulScriptEngine ScriptEngine
Definition: C4Globals.cpp:43
C4StringTable Strings
Definition: C4Globals.cpp:42
int iResult
Definition: C4GroupMain.cpp:40
bool DebugLogF(const char *strMessage ...)
Definition: C4Log.cpp:290
#define a
@ P_Name
@ P_Priority
@ P_CommandTarget
@ P_Destruction
@ P_Effect
@ P_Timer
@ P_Prototype
@ P_Start
@ P_Time
@ P_Target
@ P_Stop
@ P_Interval
@ P_LAST
@ P_Construction
@ P_Damage
C4Value C4VInt(int32_t i)
Definition: C4Value.h:239
C4Value C4VString(C4String *pStr)
Definition: C4Value.h:243
bool SWildcardMatchEx(const char *szString, const char *szWildcard)
Definition: Standard.cpp:635
#define sprintf
Definition: Standard.h:162
T Abs(T val)
Definition: Standard.h:42
StdPtrAdapt< T > mkPtrAdaptNoNull(T *&rpObj)
Definition: StdAdaptors.h:638
StdParameterAdapt< T, P > mkParAdapt(T &&rObj, P &&rPar)
Definition: StdAdaptors.h:490
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
bool WildcardMatch(const char *szWildcard, const char *szString)
Definition: StdFile.cpp:396
int iCnt
Definition: TstC4NetIO.cpp:32
virtual void OnError(const char *msg)=0
const char * what() const noexcept override
Definition: C4Aul.cpp:59
C4Value Exec(C4PropList *p=nullptr, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4AulFunc.h:72
bool GetGlobalConstant(const char *szName, C4Value *pTargetValue)
Definition: C4Aul.cpp:133
C4AulErrorHandler * GetErrorHandler() const
Definition: C4Aul.h:173
void AssignCallbackFunctions()
Definition: C4Effect.cpp:27
int CallStop(int reason, bool temporary)
Definition: C4Effect.cpp:435
C4Value 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)
Definition: C4Effect.cpp:409
static C4Effect * New(C4PropList *pForObj, C4Effect **ppEffectList, C4String *szName, int32_t iPrio, int32_t iTimerInterval, C4PropList *pCmdTarget, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4)
Definition: C4Effect.cpp:91
bool IsActive()
Definition: C4Effect.h:112
C4AulFunc * pFnTimer
Definition: C4Effect.h:81
int32_t iPriority
Definition: C4Effect.h:72
~C4Effect() override
Definition: C4Effect.cpp:164
void DoDamage(int32_t &riDamage, int32_t iDamageType, int32_t iCausePlr)
Definition: C4Effect.cpp:394
C4Effect * pNext
Definition: C4Effect.h:75
C4PropList * GetCallbackScript()
Definition: C4Effect.cpp:40
C4PropList * Target
Definition: C4Effect.h:79
void FlipActive()
Definition: C4Effect.h:111
C4ValueArray * GetProperties() const override
Definition: C4Effect.cpp:665
C4Effect * Check(const char *szCheckEffect, int32_t iPrio, int32_t iTimer, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4)
Definition: C4Effect.cpp:249
void TempRemoveUpperEffects(bool fTempRemoveThis, C4Effect **ppLastRemovedEffect)
Definition: C4Effect.cpp:496
C4AulFunc * pFnStart
Definition: C4Effect.h:82
void Denumerate(C4ValueNumbers *) override
Definition: C4Effect.cpp:176
C4AulFunc * pFnDamage
Definition: C4Effect.h:84
void Register(C4Effect **ppEffectList, int32_t iPrio)
Definition: C4Effect.cpp:71
void CallDamage(int32_t &damage, int damagetype, int plr)
Definition: C4Effect.cpp:462
void ResetProperty(C4String *k) override
Definition: C4Effect.cpp:625
int32_t iTime
Definition: C4Effect.h:73
bool GetPropertyByS(const C4String *k, C4Value *pResult) const override
Definition: C4Effect.cpp:648
void SetPropertyByS(C4String *k, const C4Value &to) override
Definition: C4Effect.cpp:598
void ClearPointers(C4PropList *pObj)
Definition: C4Effect.cpp:191
void ReAssignCallbackFunctions()
Definition: C4Effect.h:127
C4AulFunc * pFnStop
Definition: C4Effect.h:82
C4AulFunc * pFnEffect
Definition: C4Effect.h:83
int32_t iInterval
Definition: C4Effect.h:73
void OnObjectChangedDef(C4PropList *pObj)
Definition: C4Effect.cpp:482
C4Effect * Get(const char *szName, int32_t iIndex=0, int32_t iMaxPriority=0)
Definition: C4Effect.cpp:210
int CallEffect(const char *effect, const C4Value &var1, const C4Value &var2, const C4Value &var3, const C4Value &var4)
Definition: C4Effect.cpp:473
int CallStart(int temporary, const C4Value &var1, const C4Value &var2, const C4Value &var3, const C4Value &var4)
Definition: C4Effect.cpp:427
C4Value CommandTarget
Definition: C4Effect.h:78
int32_t GetCount(const char *szMask, int32_t iMaxPriority=0)
Definition: C4Effect.cpp:236
void Kill()
Definition: C4Effect.cpp:343
C4Effect * Init(C4PropList *pForObj, int32_t iPrio, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4)
Definition: C4Effect.cpp:103
bool IsDead()
Definition: C4Effect.h:110
static void Execute(C4Effect **ppEffectList)
Definition: C4Effect.cpp:297
void ClearAll(int32_t iClearFlag)
Definition: C4Effect.cpp:369
int CallTimer(int time)
Definition: C4Effect.cpp:443
void TempReaddUpperEffects(C4Effect *pLastReaddEffect)
Definition: C4Effect.cpp:521
void CompileFunc(StdCompiler *pComp, C4PropList *Owner, C4ValueNumbers *)
Definition: C4Effect.cpp:541
void SetDead()
Definition: C4Effect.cpp:205
virtual C4Object * GetObject()
Definition: C4PropList.cpp:636
C4AulFunc * GetFunc(C4PropertyName k) const
Definition: C4PropList.h:109
virtual const char * GetName() const
Definition: C4PropList.cpp:618
virtual C4ValueArray * GetProperties() const
Definition: C4PropList.cpp:883
virtual class C4PropListStatic * IsStatic()
Definition: C4PropList.h:89
int32_t Status
Definition: C4PropList.h:173
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
Definition: C4PropList.cpp:726
virtual void SetOnFire(bool OnFire)
Definition: C4PropList.h:73
virtual void ResetProperty(C4String *k)
Definition: C4PropList.cpp:961
virtual C4PropListNumbered * GetPropListNumbered()
Definition: C4PropList.cpp:672
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4PropList.h:114
virtual void SetPropertyByS(C4String *k, const C4Value &to)
Definition: C4PropList.cpp:940
friend class C4Value
Definition: C4PropList.h:170
void SetProperty(C4PropertyName k, const C4Value &to)
Definition: C4PropList.h:124
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *numbers)
Definition: C4PropList.cpp:156
void RefCompileFunc(StdCompiler *pComp, C4ValueNumbers *numbers) const
Definition: C4PropList.cpp:216
const char * GetCStr() const
Definition: C4StringTable.h:49
C4String P[P_LAST]
void SetPropList(C4PropList *PropList)
Definition: C4Value.h:141
int32_t getInt() const
Definition: C4Value.h:112
C4PropList * _getPropList() const
Definition: C4Value.h:129
C4String * getStr() const
Definition: C4Value.h:117
void Set0()
Definition: C4Value.h:332
void SetObjectEnum(int i)
Definition: C4Value.h:142
C4PropList * getPropList() const
Definition: C4Value.h:116
void Denumerate(C4ValueNumbers *)
Definition: C4Value.cpp:251
virtual bool Separator(Sep eSep=SEP_SEP)
Definition: StdCompiler.h:119
void Value(const T &rStruct)
Definition: StdCompiler.h:161
bool isSerializer()
Definition: StdCompiler.h:54
virtual void String(char *szString, size_t iMaxLength, RawCompileType eType=RCT_Escaped)=0
virtual bool isDeserializer()
Definition: StdCompiler.h:53
virtual bool hasNaming()
Definition: StdCompiler.h:58