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 /* That which fills the world with life */
19 
20 #ifndef INC_C4Object
21 #define INC_C4Object
22 
23 #include "game/C4GameScript.h"
24 #include "graphics/C4Facet.h"
25 #include "object/C4Id.h"
26 #include "object/C4ObjectPtr.h"
27 #include "object/C4Sector.h"
28 #include "object/C4Shape.h"
29 #include "script/C4PropList.h"
30 #include "script/C4Value.h"
31 
32 /* Object status */
33 
34 #define C4OS_DELETED  0
35 #define C4OS_NORMAL   1
36 #define C4OS_INACTIVE 2
37 
38 /* Action.Dir is the direction the object is actually facing. */
39 
40 #define DIR_None  0
41 #define DIR_Left  0
42 #define DIR_Right 1
43 
44 /* Action.ComDir tells an active object which way it ought to be going.
45    If you set the ComDir to COMD_Stop, the object won't sit still immediately
46    but will try to slow down according to it's current Action. ComDir values
47    circle clockwise from COMD_Up 1 through COMD_UpLeft 8. */
48 
49 #define COMD_None       -1
50 #define COMD_Stop       0
51 #define COMD_Up         1
52 #define COMD_UpRight    2
53 #define COMD_Right      3
54 #define COMD_DownRight  4
55 #define COMD_Down       5
56 #define COMD_DownLeft   6
57 #define COMD_Left       7
58 #define COMD_UpLeft     8
59 
60 /* Visibility values tell conditions for an object's visibility */
61 
62 #define VIS_All     0
63 #define VIS_None    1
64 #define VIS_Owner   2
65 #define VIS_Allies  4
66 #define VIS_Enemies 8
67 #define VIS_Select  16
68 #define VIS_God     32
69 #define VIS_LayerToggle 64
70 #define VIS_OverlayOnly 128
71 #define VIS_Editor      256
72 
73 
74 class C4Action
75 {
76 public:
77 	C4Action();
78 	~C4Action();
79 public:
80 	int32_t Dir;
81 	int32_t DrawDir; // NoSave // - needs to be calculated for old-style objects.txt anyway
82 	int32_t ComDir;
83 	int32_t Time;
84 	int32_t Data;
85 	int32_t Phase,PhaseDelay;
86 	int32_t t_attach; // SyncClearance-NoSave //
87 	C4ObjectPtr Target,Target2;
88 	C4Facet Facet; // NoSave //
89 	int32_t FacetX,FacetY; // NoSave //
90 	StdMeshInstanceAnimationNode* Animation; // NoSave //
91 public:
92 	void Default();
93 	void CompileFunc(StdCompiler *pComp);
94 
95 	// BRIDGE procedure: data mask
96 	void SetBridgeData(int32_t iBridgeTime, bool fMoveClonk, bool fWall, int32_t iBridgeMaterial);
97 	void GetBridgeData(int32_t &riBridgeTime, bool &rfMoveClonk, bool &rfWall, int32_t &riBridgeMaterial);
98 };
99 
100 class C4Object: public C4PropListNumbered
101 {
102 private:
103 	void UpdateInMat();
104 	void Splash();
105 public:
106 	C4Object();
107 	~C4Object() override;
108 	C4ID id;
109 	int32_t RemovalDelay; // NoSave //
110 	int32_t Owner;
111 	int32_t Controller;
112 	int32_t LastEnergyLossCausePlayer; // last player that caused an energy loss to this Clonk (used to trace kills when player tumbles off a cliff, etc.)
113 	int32_t Category;
114 	int32_t old_x, old_y; C4LArea Area; // position as currently seen by Game.Objecets.Sectors. UpdatePos to sync.
115 	int32_t Mass, OwnMass;
116 	int32_t Damage;
117 	int32_t Energy;
118 	int32_t Breath;
119 	int32_t InMat; // SyncClearance-NoSave //
120 	uint32_t Color;
121 	int32_t Audible, AudiblePan, AudiblePlayer; // NoSave //
122 	int32_t lightRange;
123 	int32_t lightFadeoutRange;
124 	uint32_t lightColor;
125 	C4Real fix_x,fix_y,fix_r; // SyncClearance-Fix //
126 	C4Real xdir,ydir,rdir;
127 	int32_t iLastAttachMovementFrame; // last frame in which Attach-movement by a SolidMask was done
128 	bool Mobile;
129 	bool Unsorted; // NoSave //
130 	bool Initializing; // NoSave //
131 	bool InLiquid;
132 	bool EntranceStatus;
133 	uint32_t t_contact; // SyncClearance-NoSave //
134 	uint32_t OCF;
135 	uint32_t Marker; // state var used by Objects::CrossCheck and C4FindObject - NoSave
136 	C4ObjectPtr Layer;
137 	C4DrawTransform *pDrawTransform; // assigned drawing transformation
138 
139 	// Menu
140 	class C4ObjectMenu *Menu; // SyncClearance-NoSave //
141 
142 	C4Facet TopFace; // NoSave //
143 	C4Def *Def;
144 	C4ObjectPtr Contained;
145 	C4ObjectInfo *Info;
146 
147 	C4Action Action;
148 	C4Shape Shape;
149 	bool fOwnVertices; // if set, vertices aren't restored from def but from end of own vtx list
150 	C4TargetRect SolidMask;
151 	bool HalfVehicleSolidMask;
152 	C4Rect PictureRect;
153 	C4NotifyingObjectList Contents;
154 	C4MaterialList *MaterialContents; // SyncClearance-NoSave //
155 	C4DefGraphics *pGraphics; // currently set object graphics
156 	StdMeshInstance* pMeshInstance; // Instance for mesh-type objects
157 	C4Effect *pEffects; // linked list of effects
158 	// particle lists that are bound to this object (either in front of behind it)
159 	class C4ParticleList *FrontParticles, *BackParticles;
160 	void ClearParticleLists();
161 
162 	uint32_t ColorMod; // color by which the object-drawing is modulated
163 	uint32_t BlitMode; // extra blitting flags (like additive, ClrMod2, etc.)
164 	bool CrewDisabled;  // CrewMember-functionality currently disabled
165 
166 	// Commands
167 	C4Command *Command;
168 
169 	StdCopyStrBuf nInfo;
170 
171 	class C4GraphicsOverlay *pGfxOverlay;  // singly linked list of overlay graphics
172 protected:
173 	bool OnFire;
174 	int32_t Con;
175 	int32_t Plane;
176 	bool Alive;
177 	C4SolidMask *pSolidMaskData; // NoSave //
178 public:
179 	void Resort();
SetPlane(int32_t z)180 	void SetPlane(int32_t z) { if (z) Plane = z; Resort(); }
GetPlane()181 	int32_t GetPlane() const { return Plane; }
182 	int32_t GetSolidMaskPlane() const;
183 	void SetCommand(int32_t iCommand, C4Object *pTarget, C4Value iTx, int32_t iTy=0, C4Object *pTarget2=nullptr, bool fControl=false, C4Value iData=C4VNull, int32_t iRetries=0, C4String *szText=nullptr);
184 	void SetCommand(int32_t iCommand, C4Object *pTarget=nullptr, int32_t iTx=0, int32_t iTy=0, C4Object *pTarget2=nullptr, bool fControl=false, C4Value iData=C4VNull, int32_t iRetries=0, C4String *szText=nullptr)
185 	{ SetCommand(iCommand, pTarget, C4VInt(iTx), iTy, pTarget2, fControl, iData, iRetries, szText); }
186 	bool AddCommand(int32_t iCommand, C4Object *pTarget, C4Value iTx, int32_t iTy=0, int32_t iUpdateInterval=0, C4Object *pTarget2=nullptr, bool fInitEvaluation=true, C4Value iData=C4VNull, bool fAppend=false, int32_t iRetries=0, C4String *szText=nullptr, int32_t iBaseMode=0);
187 	bool AddCommand(int32_t iCommand, C4Object *pTarget=nullptr, int32_t iTx=0, int32_t iTy=0, int32_t iUpdateInterval=0, C4Object *pTarget2=nullptr, bool fInitEvaluation=true, C4Value iData=C4VNull, bool fAppend=false, int32_t iRetries=0, C4String *szText=nullptr, int32_t iBaseMode=0)
188 	{ return AddCommand(iCommand, pTarget, C4VInt(iTx), iTy, iUpdateInterval, pTarget2, fInitEvaluation, iData, fAppend, iRetries, szText, iBaseMode); }
189 	C4Command *FindCommand(int32_t iCommandType) const; // find a command of the given type
190 	void ClearCommand(C4Command *pUntil);
191 	void ClearCommands();
192 	void DrawSelectMark(C4TargetFacet &cgo) const;
193 	void UpdateActionFace();
194 	void SyncClearance();
195 	void SetSolidMask(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY);
196 	void SetHalfVehicleSolidMask(bool set);
197 	bool CheckSolidMaskRect(); // clip bounds of SolidMask in graphics - return whether the solidmask still exists
198 	bool MenuCommand(const char *szCommand);
199 
200 	void Clear();
201 	void ClearInfo(C4ObjectInfo *pInfo);
202 	bool AssignInfo();
203 	bool ValidateOwner();
204 	bool AssignLightRange();
205 	void DrawPicture(C4Facet &cgo, bool fSelected=false, C4DrawTransform* transform=nullptr);
206 	void Picture2Facet(C4FacetSurface &cgo); // set picture to facet, or create facet in current size and draw if specific states are being needed
207 	void Default();
208 	bool Init(C4PropList *ndef, C4Object *pCreator,
209 	          int32_t owner, C4ObjectInfo *info,
210 	          int32_t nx, int32_t ny, int32_t nr,
211 	          C4Real nxdir, C4Real nydir, C4Real nrdir, int32_t iController);
212 	void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
213 	void Denumerate(C4ValueNumbers *) override;
214 	void DrawLine(C4TargetFacet &cgo, int32_t at_player);
215 	bool SetPhase(int32_t iPhase);
216 	void AssignRemoval(bool fExitContents=false);
217 	enum DrawMode { ODM_Normal=0, ODM_Overlay=1, ODM_BaseOnly=2 };
218 	void Draw(C4TargetFacet &cgo, int32_t iByPlayer = -1, DrawMode eDrawMode=ODM_Normal, float offX=0, float offY=0);
219 	void DrawTopFace(C4TargetFacet &cgo, int32_t iByPlayer = -1, DrawMode eDrawMode=ODM_Normal, float offX=0, float offY=0);
220 	void DrawActionFace(C4TargetFacet &cgo, float offX, float offY) const;
221 	void DrawFace(C4TargetFacet &cgo, float offX, float offY, int32_t iPhaseX=0, int32_t iPhaseY=0) const;
222 	void DrawFaceImpl(C4TargetFacet &cgo, bool action, float fx, float fy, float fwdt, float fhgt, float tx, float ty, float twdt, float thgt, C4DrawTransform* transform) const;
223 	void Execute();
224 	void ClearPointers(C4Object *ptr);
225 	bool ExecMovement();
226 	void ExecAction();
227 	bool ExecLife();
228 	bool ExecuteCommand();
229 	void AssignDeath(bool fForced); // assigns death - if forced, it's killed even if an effect stopped this
230 	void ContactAction();
231 	void NoAttachAction();
232 	void DoMovement();
233 	void Stabilize();
234 	void SetOCF();
235 	void UpdateOCF(); // Update fluctuant OCF
236 	void UpdateShape(bool bUpdateVertices=true);
237 	void UpdatePos(); // pos/shape changed
238 	void UpdateSolidMask(bool fRestoreAttachedObjects);
239 	void UpdateMass();
240 	bool ChangeDef(C4ID idNew);
241 	void UpdateFace(bool bUpdateShape, bool fTemp=false);
242 	void UpdateGraphics(bool fGraphicsChanged, bool fTemp=false); // recreates solidmasks (if fGraphicsChanged), validates Color
243 	void UpdateFlipDir(); // applies new flipdir to draw transform matrix; creates/deletes it if necessary
244 	bool At(int32_t ctx, int32_t cty) const;
245 	bool At(int32_t ctx, int32_t cty, DWORD &ocf) const;
246 	void GetOCFForPos(int32_t ctx, int32_t cty, DWORD &ocf) const;
247 	bool CloseMenu(bool fForce);
248 	bool ActivateMenu(int32_t iMenu, int32_t iMenuSelect=0, int32_t iMenuData=0, int32_t iMenuPosition=0, C4Object *pTarget=nullptr);
249 	int32_t ContactCheck(int32_t atx, int32_t aty, uint32_t *border_hack_contacts=nullptr, bool collide_halfvehic=false);
250 	bool Contact(int32_t cnat);
251 	void StopAndContact(C4Real & ctco, C4Real limit, C4Real & speed, int32_t cnat);
252 	enum { SAC_StartCall = 1, SAC_EndCall = 2, SAC_AbortCall = 4 };
253 	C4PropList* GetAction() const;
254 	bool SetAction(C4PropList * Act, C4Object *pTarget=nullptr, C4Object *pTarget2=nullptr, int32_t iCalls = SAC_StartCall | SAC_AbortCall, bool fForce = false);
255 	bool SetActionByName(C4String * ActName, C4Object *pTarget=nullptr, C4Object *pTarget2=nullptr, int32_t iCalls = SAC_StartCall | SAC_AbortCall, bool fForce = false);
256 	bool SetActionByName(const char * szActName, C4Object *pTarget=nullptr, C4Object *pTarget2=nullptr, int32_t iCalls = SAC_StartCall | SAC_AbortCall, bool fForce = false);
257 	void SetDir(int32_t tdir);
SetCategory(int32_t Category)258 	void SetCategory(int32_t Category) { this->Category = Category; Resort(); SetOCF(); }
259 	int32_t GetProcedure() const;
260 	bool Enter(C4Object *pTarget, bool fCalls=true, bool fCopyMotion=true, bool *pfRejectCollect=nullptr);
261 	bool Exit(int32_t iX=0, int32_t iY=0, int32_t iR=0, C4Real iXDir=Fix0, C4Real iYDir=Fix0, C4Real iRDir=Fix0, bool fCalls=true);
262 	void CopyMotion(C4Object *from);
263 	void ForcePosition(C4Real tx, C4Real ty);
264 	void MovePosition(int32_t dx, int32_t dy);
265 	void MovePosition(C4Real dx, C4Real dy);
266 	void DoMotion(int32_t mx, int32_t my);
267 	bool ActivateEntrance(int32_t by_plr, C4Object *by_obj);
268 	void DoDamage(int32_t iLevel, int32_t iCausedByPlr, int32_t iCause);
269 	void DoEnergy(int32_t iChange, bool fExact, int32_t iCause, int32_t iCausedByPlr);
270 	void UpdatLastEnergyLossCause(int32_t iNewCausePlr);
271 	void DoBreath(int32_t iChange);
272 	void DoCon(int32_t iChange, bool grow_from_center);
GetCon()273 	int32_t GetCon() const { return Con; }
274 	void DoExperience(int32_t change);
275 	bool Promote(int32_t torank, bool exception, bool fForceRankName);
276 	bool Push(C4Real txdir, C4Real dforce, bool fStraighten);
277 	bool Lift(C4Real tydir, C4Real dforce);
278 	void Fling(C4Real txdir, C4Real tydir, bool fAddSpeed); // set/add given speed to current, setting jump/tumble-actions
279 	C4Object* CreateContents(C4PropList *);
280 	bool CreateContentsByList(C4IDList &idlist);
281 	BYTE GetArea(int32_t &aX, int32_t &aY, int32_t &aWdt, int32_t &aHgt) const;
addtop()282 	inline int32_t addtop() const { return std::max<int32_t>(18-Shape.Hgt,0); } // Minimum top action size for build check
Left()283 	inline int32_t Left() const { return GetX()+Shape.x; } // left border of shape
Top()284 	inline int32_t Top() const { return GetY()+Shape.y-addtop(); } // top border of shape (+build-top)
Width()285 	inline int32_t Width() const { return Shape.Wdt; } // width of shape
Height()286 	inline int32_t Height() const { return Shape.Hgt+addtop(); } // height of shape (+build-top)
GetX()287 	inline int32_t GetX() const { return fixtoi(fix_x); }
GetY()288 	inline int32_t GetY() const { return fixtoi(fix_y); }
GetR()289 	inline int32_t GetR() const { return fixtoi(fix_r); }
GetFixedX()290 	inline C4Real GetFixedX() const { return fix_x; }
GetFixedY()291 	inline C4Real GetFixedY() const { return fix_y; }
GetFixedR()292 	inline C4Real GetFixedR() const { return fix_r; }
293 	BYTE GetEntranceArea(int32_t &aX, int32_t &aY, int32_t &aWdt, int32_t &aHgt) const;
294 	BYTE GetMomentum(C4Real &rxdir, C4Real &rydir) const;
295 	C4Real GetSpeed() const;
296 	StdStrBuf GetDataString();
297 	void SetName (const char *NewName = nullptr) override;
298 	int32_t GetValue(C4Object *pInBase, int32_t iForPlayer);
299 	bool SetOwner(int32_t iOwner);
300 	bool SetLightRange(int32_t iToRange, int32_t iToFadeoutRange);
GetLightColor()301 	uint32_t GetLightColor() const { return lightColor; }
302 	bool SetLightColor(uint32_t iValue);
SetOnFire(bool OnFire)303 	void SetOnFire(bool OnFire) override { this->OnFire = OnFire; SetOCF(); }
GetOnFire()304 	bool GetOnFire() const { return OnFire; }
SetAlive(bool Alive)305 	void SetAlive(bool Alive) { this->Alive = Alive; SetOCF(); }
GetAlive()306 	bool GetAlive() const { return Alive; }
307 	void UpdateLight();
308 	void SetAudibilityAt(C4TargetFacet &cgo, int32_t iX, int32_t iY, int32_t player);
309 	bool IsVisible(int32_t iForPlr, bool fAsOverlay) const;  // return whether an object is visible for the given player
310 	void SetRotation(int32_t nr);
311 	void PrepareDrawing() const;  // set blit modulation and/or additive blitting
312 	void FinishedDrawing() const; // reset any modulation
313 	void DrawSolidMask(C4TargetFacet &cgo) const;     // draw topface image only
314 	bool Collect(C4Object *pObj);           // add object to contents if it can be carried - no OCF and range checks are done!
315 	bool GrabInfo(C4Object *pFrom);         // grab info object from other object
316 	bool ShiftContents(bool fShiftBack, bool fDoCalls); // rotate through contents
317 	void DirectComContents(C4Object *pTarget, bool fDoCalls);   // direct com: scroll contents to given ID
318 	void GetParallaxity(int32_t *parX, int32_t *parY) const;
319 	bool GetDrawPosition(const C4TargetFacet & cgo, float & resultx, float & resulty, float & resultzoom) const; // converts the object's position into screen coordinates
320 	bool GetDrawPosition(const C4TargetFacet & cgo, float x, float y, float zoom, float & resultx, float & resulty, float & resultzoom) const; // converts object coordinates into screen coordinates
321 	bool IsInLiquidCheck() const;                        // returns whether the Clonk is within liquid material
322 	void UpdateInLiquid(); // makes splash when a liquid is entered
323 	void GrabContents(C4Object *pFrom); // grab all contents that don't reject it
324 	bool GetDragImage(C4Object **drag_object, C4Def **drag_id) const; // return true if object is draggable; assign drag_object/drag_id to gfx to be used for dragging
325 	int32_t AddObjectAndContentsToArray(C4ValueArray *target_array, int32_t index=0); // add self, contents and child contents count recursively to value array. Return index after last added item.
326 
327 protected:
328 	void SideBounds(C4Real &ctcox);       // apply bounds at side; regarding bourder bound and pLayer
329 	void VerticalBounds(C4Real &ctcoy);   // apply bounds at top and bottom; regarding border bound and pLayer
330 
331 public:
BoundsCheck(C4Real & ctcox,C4Real & ctcoy)332 	void BoundsCheck(C4Real &ctcox, C4Real &ctcoy) // do bound checks, correcting target positions as necessary and doing contact-calls
333 	{ SideBounds(ctcox); VerticalBounds(ctcoy); }
334 
335 	bool DoSelect(); // cursor callback if not disabled
336 	void UnSelect(); // unselect callback
337 	void GetViewPos(float &riX, float &riY, float tx, float ty, const C4Facet &fctViewport) const;
338 	void GetViewPosPar(float &riX, float &riY, float tx, float ty, const C4Facet &fctViewport) const;   // get position this object is seen at, calculating parallaxity
339 	bool PutAwayUnusedObject(C4Object *pToMakeRoomForObject); // either directly put the least-needed object away, or add a command to do it - return whether successful
340 
GetGraphics()341 	C4DefGraphics *GetGraphics() const { return pGraphics; } // return current object graphics
342 	bool SetGraphics(const char *szGraphicsName=nullptr, C4Def *pSourceDef=nullptr);      // set used graphics for object; if szGraphicsName or *szGraphicsName are nullptr, the default graphics of the given def are used; pSourceDef defaults to own def
343 	bool SetGraphics(C4DefGraphics *pNewGfx, bool fUpdateData);      // set used graphics for object
344 
345 	class C4GraphicsOverlay *GetGraphicsOverlay(int32_t iForID) const;  // get specified gfx overlay
346 	class C4GraphicsOverlay *GetGraphicsOverlay(int32_t iForID, bool fCreate);  // get specified gfx overlay; create if not existant and specified
347 	bool RemoveGraphicsOverlay(int32_t iOverlayID);                             // remove specified overlay from the overlay list; return if found
348 	bool HasGraphicsOverlayRecursion(const C4Object *pCheckObj) const; // returns whether, at any overlay recursion depth, the given object appears as an MODE_Object-overlay
349 	void UpdateScriptPointers(); // update ptrs to C4AulScript *
350 
351 	bool StatusActivate();   // put into active list
352 	bool StatusDeactivate(bool fClearPointers); // put into inactive list
353 
354 	void ClearContentsAndContained(bool fDoCalls=true); // exit from container and eject contents (doing calbacks)
355 
356 	bool AdjustWalkRotation(int32_t iRangeX, int32_t iRangeY, int32_t iSpeed);
357 
358 	StdStrBuf GetInfoString(); // return def desc plus effects
359 
360 	bool CanConcatPictureWith(C4Object *pOtherObject) const; // return whether this object should be grouped with the other in activation lists, contents list, etc.
361 
362 	bool IsMoveableBySolidMask(int ComparisonPlane) const;
363 
364 	// This function is used for:
365 	// -Objects to be removed when a player is removed
366 	// -Objects that are not to be saved in "SaveScenario"-mode
367 	bool IsPlayerObject(int32_t iPlayerNumber=NO_OWNER) const;// true for any object that belongs to any player (NO_OWNER) or a specified player
368 
369 	// This function is used for:
370 	// -Objects that are not to be saved in "SaveScenario"-mode
371 	bool IsUserPlayerObject();// true for any object that belongs to any player (NO_OWNER) or a specified player
372 
373 	// overloaded from C4PropList
GetObject()374 	C4Object * GetObject() override { return this; }
GetObject()375 	C4Object const * GetObject() const override { return this; }
376 	void SetPropertyByS(C4String * k, const C4Value & to) override;
377 	void ResetProperty(C4String * k) override;
378 	bool GetPropertyByS(const C4String *k, C4Value *pResult) const override;
379 	C4ValueArray * GetProperties() const override;
380 };
381 
382 #endif
383