1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design)
5 * Copyright (c) 2017-2022, The LegacyClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16
17// C4AulFun-based effects assigned to an object
18// an effect itself only supplies the callback mechanism for effects assigned to objects
19// the effect itself supplies the callback mechanism for creation, destruction, timers
20// and overlapped effects
21/* Also contains some helper functions for various landscape effects */
22
23#pragma once
24
25#include "C4Aul.h"
26#include "C4Constants.h"
27#include "C4DeletionTrackable.h"
28#include "C4EnumeratedObjectPtr.h"
29#include "C4ValueList.h"
30
31typedef unsigned long C4ID;
32
33// callback return values
34#define C4Fx_OK 0 // generic standard behaviour for all effect callbacks
35
36#define C4Fx_Effect_Deny -1 // delete effect
37#define C4Fx_Effect_Annul -2 // delete effect, because it has annulled a countereffect
38#define C4Fx_Effect_AnnulCalls -3 // delete effect, because it has annulled a countereffect; temp readd countereffect
39
40#define C4Fx_Execute_Kill -1 // execute callback: Remove effect now
41
42#define C4Fx_Stop_Deny -1 // deny effect removal
43#define C4Fx_Start_Deny -1 // deny effect start
44
45// parameters for effect callbacks
46#define C4FxCall_Normal 0 // normal call; effect is being added or removed
47#define C4FxCall_Temp 1 // temp call; effect is being added or removed in responce to a lower-level effect change
48#define C4FxCall_TempAddForRemoval 2 // temp call; effect is being added because it had been temp removed and is now removed forever
49#define C4FxCall_RemoveClear 3 // effect is being removed because object is being removed
50#define C4FxCall_RemoveDeath 4 // effect is being removed because object died - return -1 to avoid removal
51
52// damage-callbacks
53#define C4FxCall_DmgScript 0 // damage through script call
54#define C4FxCall_DmgBlast 1 // damage through blast
55#define C4FxCall_DmgFire 2 // damage through fire
56#define C4FxCall_DmgChop 3 // damage through chopping
57
58// energy loss callbacks
59#define C4FxCall_EngScript 32 // energy loss through script call
60#define C4FxCall_EngBlast 33 // energy loss through blast
61#define C4FxCall_EngObjHit 34 // energy loss through object hitting the living
62#define C4FxCall_EngFire 35 // energy loss through fire
63#define C4FxCall_EngBaseRefresh 36 // energy reload in base (also by base object, but that's normally not called)
64#define C4FxCall_EngAsphyxiation 37 // energy loss through asphyxiaction
65#define C4FxCall_EngCorrosion 38 // energy loss through corrosion (acid)
66#define C4FxCall_EngStruct 39 // regular structure energy loss (normally not called)
67#define C4FxCall_EngGetPunched 40 // energy loss during fighting
68
69// fire drawing modes
70#define C4Fx_FireMode_Default 0 // determine mode by category
71#define C4Fx_FireMode_LivingVeg 2 // C4D_Living and C4D_StaticBack
72#define C4Fx_FireMode_StructVeh 1 // C4D_Structure and C4D_Vehicle
73#define C4Fx_FireMode_Object 3 // other (C4D_Object and no bit set (magic))
74#define C4Fx_FireMode_Last 3 // largest valid fire mode
75
76// generic object effect
77class C4Effect : private C4DeletionTrackable
78{
79public:
80 char Name[C4MaxDefString + 1]; // name of effect
81 C4EnumeratedObjectPtr pCommandTarget; // target object for script callbacks - if deleted, the effect is removed without callbacks
82 C4ID idCommandTarget; // ID of command target definition
83
84 int32_t iPriority; // effect priority for sorting into effect list; -1 indicates a dead effect
85 C4ValueList EffectVars; // custom effect variables
86 int32_t iTime, iIntervall; // effect time; effect callback intervall
87 int32_t iNumber; // effect number for addressing
88
89 C4Effect *pNext; // next effect in linked list
90
91protected:
92 // presearched callback functions for faster calling
93 C4AulFunc *pFnTimer; // timer function Fx%sTimer
94 C4AulFunc *pFnStart, *pFnStop; // init/deinit-functions Fx%sStart, Fx%sStop
95 C4AulFunc *pFnEffect; // callback if other effect tries to register
96 C4AulFunc *pFnDamage; // callback when owned object gets damage
97
98 void AssignCallbackFunctions(); // resolve callback function names
99
100public:
101 C4Effect(C4Object *pForObj, const char *szName, int32_t iPrio, int32_t iTimerIntervall, C4Object *pCmdTarget, C4ID idCmdTarget, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4, bool fDoCalls, int32_t &riStoredAsNumber, bool passErrors = false);
102 C4Effect(StdCompiler *pComp); // ctor: compile
103 ~C4Effect(); // dtor - deletes all following effects
104
105 void EnumeratePointers(); // object pointers to numbers
106 void DenumeratePointers(); // numbers to object pointers
107 void ClearPointers(C4Object *pObj); // clear all pointers to object - may kill some effects w/o callback, because the callback target is lost
108
109 void SetDead() { iPriority = 0; } // mark effect to be removed in next execution cycle
110 bool IsDead() { return !iPriority; } // return whether effect is to be removed
111 void FlipActive() { iPriority *= -1; } // alters activation status
112 bool IsActive() { return iPriority > 0; } // returns whether effect is active
113 bool IsInactiveAndNotDead() { return iPriority < 0; } // as the name says
114
115 C4Effect *Get(const char *szName, int32_t iIndex = 0, int32_t iMaxPriority = 0); // get effect by name
116 C4Effect *Get(int32_t iNumber, bool fIncludeDead, int32_t iMaxPriority = 0); // get effect by number
117 int32_t GetCount(const char *szMask, int32_t iMaxPriority = 0); // count effects that match the mask
118 int32_t Check(C4Object *pForObj, const char *szCheckEffect, int32_t iPrio, int32_t iTimer, const C4Value &rVal1 = C4VNull, const C4Value &rVal2 = C4VNull, const C4Value &rVal3 = C4VNull, const C4Value &rVal4 = C4VNull, bool passErrors = false); // do some effect callbacks
119 C4AulScript *GetCallbackScript(); // get script context for effect callbacks
120
121 void Execute(C4Object *pObj); // execute all effects
122 void Kill(C4Object *pObj); // mark this effect deleted and do approprioate calls
123 void ClearAll(C4Object *pObj, int32_t iClearFlag); // kill all effects doing removal calls w/o reagard of inactive effects
124 void DoDamage(C4Object *pObj, int32_t &riDamage, int32_t iDamageType, int32_t iCausePlr); // ask all effects for damage
125
126 C4Value DoCall(C4Object *pObj, const char *szFn, const C4Value &rVal1 = C4VNull, const C4Value &rVal2 = C4VNull, const C4Value &rVal3 = C4VNull, const C4Value &rVal4 = C4VNull, const C4Value &rVal5 = C4VNull, const C4Value &rVal6 = C4VNull, const C4Value &rVal7 = C4VNull, bool passErrors = false, bool convertNilToIntBool = true); // custom call
127
128 void ReAssignCallbackFunctions()
129 {
130 AssignCallbackFunctions();
131 }
132
133 void ReAssignAllCallbackFunctions()
134 {
135 ReAssignCallbackFunctions();
136 if (pNext) pNext->ReAssignAllCallbackFunctions();
137 }
138
139 void OnObjectChangedDef(C4Object *pObj);
140
141 void CompileFunc(StdCompiler *pComp);
142
143protected:
144 void TempRemoveUpperEffects(C4Object *pObj, bool fTempRemoveThis, C4Effect **ppLastRemovedEffect); // temp remove all effects with higher priority
145 void TempReaddUpperEffects(C4Object *pObj, C4Effect *pLastReaddEffect); // temp remove all effects with higher priority
146};
147
148// ctor for StdPtrAdapt
149inline void CompileNewFunc(C4Effect *&pRes, StdCompiler *pComp) { pRes = new C4Effect(pComp); }
150
151// fire effect constants
152#define MaxFirePhase 15
153#define C4Fx_Fire "Fire"
154#define C4Fx_AnyFire "*Fire*"
155#define C4Fx_Internal "Int*"
156#define C4Fx_FirePriority 100
157#define C4Fx_FireTimer 1
158
159// fire effect
160int32_t FnFxFireStart(C4AulContext *ctx, C4Object *pObj, int32_t iNumber, int32_t iTemp, int32_t iCausedBy, bool fBlasted, C4Object *pIncineratingObject);
161int32_t FnFxFireTimer(C4AulContext *ctx, C4Object *pObj, int32_t iNumber, int32_t iTime);
162int32_t FnFxFireStop(C4AulContext *ctx, C4Object *pObj, int32_t iNumber, int32_t iReason, bool fTemp);
163C4String *FnFxFireInfo(C4AulContext *ctx, C4Object *pObj, int32_t iNumber);
164class C4Value &FxFireVarCausedBy(C4Effect *pEffect);
165
166// some other hardcoded engine effects
167void Splash(int32_t tx, int32_t ty, int32_t amt, C4Object *pByObj);
168void Explosion(int32_t tx, int32_t ty, int32_t level, C4Object *inobj, int32_t iCausedBy, C4Object *pByObj, C4ID idEffect, const char *szEffect);
169void Smoke(int32_t tx, int32_t ty, int32_t level, uint32_t dwClr = 0);
170void BubbleOut(int32_t tx, int32_t ty);
171