OpenClonk
C4ObjectScript.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 #include "C4Include.h"
20 
21 #include "control/C4Teams.h"
22 #include "graphics/C4Draw.h"
24 #include "gui/C4GameMessage.h"
25 #include "landscape/C4Material.h"
26 #include "landscape/C4Particles.h"
27 #include "lib/C4Random.h"
28 #include "lib/StdMeshMath.h"
29 #include "object/C4Command.h"
30 #include "object/C4DefList.h"
31 #include "object/C4MeshAnimation.h"
33 #include "object/C4ObjectCom.h"
34 #include "object/C4ObjectInfo.h"
35 #include "object/C4ObjectMenu.h"
36 #include "player/C4Player.h"
37 #include "player/C4PlayerList.h"
38 #include "player/C4RankSystem.h"
39 #include "script/C4Aul.h"
40 #include "script/C4AulDefFunc.h"
41 
42 bool C4ValueToMatrix(C4Value& value, StdMeshMatrix* matrix)
43 {
44  const C4ValueArray* array = value.getArray();
45  if (!array)
46  {
47  return false;
48  }
49  return C4ValueToMatrix(*array, matrix);
50 }
51 
52 bool C4ValueToMatrix(const C4ValueArray& array, StdMeshMatrix* matrix)
53 {
54  if (array.GetSize() != 12)
55  {
56  return false;
57  }
58 
59  StdMeshMatrix& trans = *matrix;
60  trans(0, 0) = array[0].getInt() / 1000.0f;
61  trans(0, 1) = array[1].getInt() / 1000.0f;
62  trans(0, 2) = array[2].getInt() / 1000.0f;
63  trans(0, 3) = array[3].getInt() / 1000.0f;
64  trans(1, 0) = array[4].getInt() / 1000.0f;
65  trans(1, 1) = array[5].getInt() / 1000.0f;
66  trans(1, 2) = array[6].getInt() / 1000.0f;
67  trans(1, 3) = array[7].getInt() / 1000.0f;
68  trans(2, 0) = array[8].getInt() / 1000.0f;
69  trans(2, 1) = array[9].getInt() / 1000.0f;
70  trans(2, 2) = array[10].getInt() / 1000.0f;
71  trans(2, 3) = array[11].getInt() / 1000.0f;
72 
73  return true;
74 }
75 
76 static bool FnChangeDef(C4Object *Obj, C4ID to_id)
77 {
78  return !!Obj->ChangeDef(to_id);
79 }
80 
81 static void FnSetSolidMask(C4Object *Obj, long iX, long iY, long iWdt, long iHgt, long iTX, long iTY)
82 {
83  Obj->SetSolidMask(iX,iY,iWdt,iHgt,iTX,iTY);
84 }
85 
86 static void FnSetHalfVehicleSolidMask(C4Object *Obj, bool set)
87 {
88  Obj->SetHalfVehicleSolidMask(set);
89 }
90 
91 static void FnDeathAnnounce(C4Object *Obj)
92 {
93  const long MaxDeathMsg=7;
94  if (Game.C4S.Head.Film)
95  {
96  return;
97  }
98  // Check if crew member has an own death message
99  if (Obj->Info && *(Obj->Info->DeathMessage))
100  {
101  GameMsgObject(Obj->Info->DeathMessage, Obj);
102  }
103  else
104  {
105  char idDeathMsg[128+1];
106  sprintf(idDeathMsg, "IDS_OBJ_DEATH%d", 1 + UnsyncedRandom(MaxDeathMsg));
107  GameMsgObject(FormatString(LoadResStr(idDeathMsg), Obj->GetName()).getData(), Obj);
108  }
109 }
110 
111 static bool FnGrabContents(C4Object *Obj, C4Object *from)
112 {
113  if (!from || Obj == from)
114  {
115  return false;
116  }
117  Obj->GrabContents(from);
118  return true;
119 }
120 
121 static bool FnPunch(C4Object *Obj, C4Object *target, long punch)
122 {
123  if (!target)
124  {
125  return false;
126  }
127  return !!ObjectComPunch(Obj, target, punch);
128 }
129 
130 static bool FnKill(C4PropList * _this, C4Object *pObj, bool fForced)
131 {
132  if (!pObj)
133  {
134  pObj = Object(_this);
135  }
136  if (!pObj || !pObj->GetAlive())
137  {
138  return false;
139  }
140  // Trace kills by player-owned objects
141  // Do not trace for NO_OWNER, because that would include e.g. the Suicide-rule
142  if (Object(_this) && ValidPlr(Object(_this)->Controller))
143  {
144  pObj->UpdatLastEnergyLossCause(Object(_this)->Controller);
145  }
146  // Do the kill
147  pObj->AssignDeath(!!fForced);
148  return true;
149 }
150 
151 static void FnFling(C4Object *Obj, long iXDir, long iYDir, long iPrec, bool fAddSpeed)
152 {
153  if (!iPrec)
154  {
155  iPrec = 1;
156  }
157  Obj->Fling(itofix(iXDir, iPrec), itofix(iYDir, iPrec), fAddSpeed);
158  // unstick from ground, because Fling command may be issued in an Action-callback,
159  // where attach-values have already been determined for that frame
160  Obj->Action.t_attach = 0;
161 }
162 
163 static bool FnJump(C4Object *Obj)
164 {
165  return !!ObjectComJump(Obj);
166 }
167 
168 static bool FnEnter(C4Object *Obj, C4Object *pTarget)
169 {
170  return !!Obj->Enter(pTarget, true, true, nullptr);
171 }
172 
173 static bool FnExit(C4Object *Obj, long tx, long ty, long tr, long txdir, long tydir, long trdir)
174 {
175  tx += Obj->GetX();
176  ty += Obj->GetY();
178  return !!Obj->Exit(tx,
179  ty+Obj->Shape.y,
180  tr,
181  itofix(txdir),itofix(tydir),
182  itofix(trdir) / 10);
183 }
184 
185 static bool FnCollect(C4Object *Obj, C4Object *pItem, bool ignoreOCF)
186 {
187  // Local call / safety
188  if (!pItem)
189  {
190  return false;
191  }
192  // Check OCF of collector (MaxCarry)
193  if ((Obj->OCF & OCF_Collection) || ignoreOCF)
194  {
195  // Collect
196  return !!Obj->Collect(pItem);
197  }
198  // Failure
199  return false;
200 }
201 
202 static void FnRemoveObject(C4Object *Obj, bool fEjectContents)
203 {
204  Obj->AssignRemoval(fEjectContents);
205 }
206 
207 static void FnSetPosition(C4Object *Obj, long iX, long iY, bool fCheckBounds, long iPrec)
208 {
209  if (!iPrec)
210  {
211  iPrec = 1;
212  }
213  C4Real i_x = itofix(iX, iPrec);
214  C4Real i_y = itofix(iY, iPrec);
215  if (fCheckBounds)
216  {
217  // BoundsCheck takes ref to C4Real and not to long
218  Obj->BoundsCheck(i_x, i_y);
219  }
220  Obj->ForcePosition(i_x, i_y);
221  // Update liquid
222  Obj->UpdateInLiquid();
223 }
224 
225 static void FnDoCon(C4Object *Obj, long iChange, long iPrec, bool bGrowFromCenter)
226 {
227  if (!iPrec)
228  {
229  iPrec = 100;
230  }
231  Obj->DoCon(FullCon*iChange / iPrec, bGrowFromCenter);
232 }
233 
234 static long FnGetCon(C4Object *Obj, long iPrec)
235 {
236  if (!iPrec)
237  {
238  iPrec = 100;
239  }
240  return iPrec * Obj->GetCon() / FullCon;
241 }
242 
243 static bool FnSetName(C4PropList * _this, C4String *pNewName, bool fSetInInfo, bool fMakeValidIfExists)
244 {
245  if (!Object(_this))
246  {
247  if (!_this)
248  {
249  throw NeedNonGlobalContext("SetName");
250  }
251  else if (fSetInInfo)
252  {
253  return false;
254  }
255  // Definition name
256  _this->SetName(FnStringPar(pNewName));
257  return true;
258  }
259  else
260  {
261  // Object name
262  if (fSetInInfo)
263  {
264  // Setting name in info
265  C4ObjectInfo *pInfo = Object(_this)->Info;
266  if (!pInfo)
267  {
268  return false;
269  }
270  const char *szName = pNewName->GetCStr();
271  // Empty names are bad; e.g., could cause problems in savegames
272  if (!szName || !*szName)
273  {
274  return false;
275  }
276  // Name must not be too long
277  if (std::strlen(szName) > C4MaxName)
278  {
279  return false;
280  }
281  // Any change at all?
282  if (SEqual(szName, pInfo->Name))
283  {
284  return true;
285  }
286  // Make sure names in info list aren't duplicated
287  // querying owner info list here isn't 100% accurate, as infos might have been stolen by other players
288  // however, there is no good way to track the original list ATM
289  C4ObjectInfoList *pInfoList = nullptr;
290  C4Player *pOwner = ::Players.Get(Object(_this)->Owner);
291  if (pOwner)
292  {
293  pInfoList = &pOwner->CrewInfoList;
294  }
295  char NameBuf[C4MaxName+1];
296  if (pInfoList && pInfoList->NameExists(szName))
297  {
298  if (!fMakeValidIfExists)
299  {
300  return false;
301  }
302  SCopy(szName, NameBuf, C4MaxName);
303  pInfoList->MakeValidName(NameBuf);
304  szName = NameBuf;
305  }
306  SCopy(szName, pInfo->Name, C4MaxName);
307  Object(_this)->SetName(); // make sure object uses info name
308  Object(_this)->Call(PSF_NameChange,&C4AulParSet(true));
309  }
310  else
311  {
312  if (!pNewName)
313  {
314  Object(_this)->SetName();
315  }
316  else
317  {
318  Object(_this)->SetName(pNewName->GetCStr());
319  }
320  Object(_this)->Call(PSF_NameChange, &C4AulParSet(false));
321  }
322  }
323  return true;
324 }
325 
326 static C4Value FnSetCrewExtraData(C4Object *Obj, C4String * DataName, const C4Value & Data)
327 {
328  const char *strDataName = FnStringPar(DataName);
329  // valid crew with info? (for great nullpointer prevention)
330  if (!Obj->Info)
331  {
332  return C4Value();
333  }
334  // Do not allow data type C4V_Array or C4V_C4Object
335  if (Data.GetType() != C4V_Nil
336  && Data.GetType() != C4V_Int
337  && Data.GetType() != C4V_Bool
338  && Data.GetType() != C4V_String)
339  {
340  return C4VNull;
341  }
342  // Get pointer on info...
343  C4ObjectInfo *pInfo = Obj->Info;
344  // no name list created yet?
345  if (!pInfo->ExtraData.pNames)
346  {
347  // Create name list
348  pInfo->ExtraData.CreateTempNameList();
349  }
350  // data name already exists?
351  long ival;
352  if ((ival = pInfo->ExtraData.pNames->GetItemNr(strDataName)) != -1)
353  {
354  pInfo->ExtraData[ival] = Data;
355  }
356  else
357  {
358  // Add name
359  pInfo->ExtraData.pNames->AddName(strDataName);
360  // Get val id & set
361  if ((ival = pInfo->ExtraData.pNames->GetItemNr(strDataName)) == -1)
362  {
363  return C4Value();
364  }
365  pInfo->ExtraData[ival] = Data;
366  }
367  // Ok, return the value that has been set
368  return Data;
369 }
370 
371 static C4Value FnGetCrewExtraData(C4Object *Obj, C4String * DataName)
372 {
373  const char *strDataName = FnStringPar(DataName);
374  // Valid crew with info?
375  if (!Obj->Info)
376  {
377  return C4Value();
378  }
379  // Get pointer on info...
380  C4ObjectInfo *pInfo = Obj->Info;
381  // No name list?
382  if (!pInfo->ExtraData.pNames)
383  {
384  return C4Value();
385  }
386  long ival = pInfo->ExtraData.pNames->GetItemNr(strDataName);
387  if (ival == -1)
388  {
389  return C4Value();
390  }
391  // return data
392  return pInfo->ExtraData[ival];
393 }
394 
395 static void FnDoEnergy(C4Object *Obj, long iChange, bool fExact, Nillable<long> iEngType, Nillable<long> iCausedBy)
396 {
397  if (iEngType.IsNil())
398  {
399  iEngType = C4FxCall_EngScript;
400  }
401  if (iCausedBy.IsNil())
402  {
403  iCausedBy = NO_OWNER;
404  }
405  Obj->DoEnergy(iChange, fExact, iEngType, iCausedBy);
406 }
407 
408 static void FnDoBreath(C4Object *Obj, long iChange)
409 {
410  Obj->DoBreath(iChange);
411 }
412 
413 static void FnDoDamage(C4Object *Obj, long iChange, Nillable<long> iDmgType, Nillable<long> iCausedBy)
414 {
415  if (iDmgType.IsNil())
416  {
417  iDmgType = C4FxCall_DmgScript;
418  }
419  if (iCausedBy.IsNil())
420  {
421  iCausedBy = NO_OWNER;
422  }
423  Obj->DoDamage(iChange, iCausedBy, iDmgType);
424 }
425 
426 static void FnSetEntrance(C4Object *Obj, bool e_status)
427 {
428  Obj->EntranceStatus = e_status;
429 }
430 
431 
432 static void FnSetXDir(C4Object *Obj, long nxdir, long iPrec)
433 {
434  // Precision (default 10.0)
435  if (!iPrec)
436  {
437  iPrec = 10;
438  }
439  // Update xdir
440  Obj->xdir = itofix(nxdir, iPrec);
441  Obj->Mobile = true;
442 }
443 
444 static void FnSetRDir(C4Object *Obj, long nrdir, long iPrec)
445 {
446  // Precision (default 10.0)
447  if (!iPrec)
448  {
449  iPrec = 10;
450  }
451  // Update rdir
452  Obj->rdir = itofix(nrdir, iPrec);
453  Obj->Mobile = true;
454 }
455 
456 static void FnSetYDir(C4Object *Obj, long nydir, long iPrec)
457 {
458  // Precision (default 10.0)
459  if (!iPrec)
460  {
461  iPrec = 10;
462  }
463  // Update ydir
464  Obj->ydir = itofix(nydir, iPrec);
465  Obj->Mobile = true;
466 }
467 
468 static void FnSetR(C4Object *Obj, long nr)
469 {
470  Obj->SetRotation(nr);
471 }
472 
473 static bool FnSetAction(C4Object *Obj, C4String *szAction,
474  C4Object *pTarget, C4Object *pTarget2, bool fDirect)
475 {
476  if (!szAction)
477  {
478  return false;
479  }
480  return !!Obj->SetActionByName(FnStringPar(szAction), pTarget, pTarget2,
482 }
483 
484 static bool FnSetActionData(C4Object *Obj, long iData)
485 {
486  if (!Obj->Status)
487  {
488  return false;
489  }
490  C4PropList* pActionDef = Obj->GetAction();
491  // Attach: check for valid vertex indices
492  if (pActionDef && (pActionDef->GetPropertyP(P_Procedure) == DFA_ATTACH))
493  {
494  if (((iData&255) >= C4D_MaxVertex) || ((iData>>8) >= C4D_MaxVertex))
495  {
496  return false;
497  }
498  }
499  // set data
500  Obj->Action.Data = iData;
501  return true;
502 }
503 
504 static void FnSetComDir(C4Object *Obj, long ncomdir)
505 {
506  Obj->Action.ComDir=ncomdir;
507 }
508 
509 static void FnSetDir(C4Object *Obj, long ndir)
510 {
511  Obj->SetDir(ndir);
512 }
513 
514 static void FnSetCategory(C4Object *Obj, long iCategory)
515 {
516  Obj->SetCategory(iCategory);
517 }
518 
519 static void FnSetAlive(C4Object *Obj, bool nalv)
520 {
521  Obj->SetAlive(nalv);
522 }
523 
524 static bool FnSetOwner(C4Object *Obj, long iOwner)
525 {
526  // Set owner
527  return !!Obj->SetOwner(iOwner);
528 }
529 
530 static bool FnSetPhase(C4Object *Obj, long iVal)
531 {
532  return !!Obj->SetPhase(iVal);
533 }
534 
535 static bool FnExecuteCommand(C4Object *Obj)
536 {
537  return !!Obj->ExecuteCommand();
538 }
539 
540 static bool FnSetCommand(C4Object *Obj, C4String * szCommand, C4Object * pTarget,
541  const C4Value & Tx, int iTy, C4Object * pTarget2,
542  const C4Value & Data, int iRetries)
543 {
544  // Command
545  if (!szCommand)
546  {
547  return false;
548  }
549  long iCommand = CommandByName(FnStringPar(szCommand));
550  if (!iCommand)
551  {
552  Obj->ClearCommands();
553  return false;
554  }
555  // Special: convert iData to szText
556  C4String *szText = nullptr;
557  if (iCommand == C4CMD_Call)
558  {
559  szText=Data.getStr();
560  }
561  // FIXME: throw if Tx isn't int
562  // Set
563  Obj->SetCommand(iCommand, pTarget, Tx, iTy, pTarget2, false, Data, iRetries, szText);
564  // Success
565  return true;
566 }
567 
568 static bool FnAddCommand(C4Object *Obj, C4String * szCommand, C4Object * pTarget,
569  const C4Value & Tx, int iTy, C4Object * pTarget2,
570  int iUpdateInterval, const C4Value & Data, int iRetries, int iBaseMode)
571 {
572  // Command
573  if (!szCommand)
574  {
575  return false;
576  }
577  long iCommand = CommandByName(FnStringPar(szCommand));
578  if (!iCommand)
579  {
580  return false;
581  }
582  // Special: convert iData to szText
583  C4String *szText = nullptr;
584  if (iCommand == C4CMD_Call)
585  {
586  szText=Data.getStr();
587  }
588  // Add
589  return Obj->AddCommand(iCommand,pTarget,Tx,iTy,iUpdateInterval,pTarget2,true,Data,false,iRetries,szText,iBaseMode);
590 }
591 
592 static bool FnAppendCommand(C4Object *Obj, C4String * szCommand, C4Object * pTarget,
593  const C4Value & Tx, int iTy, C4Object * pTarget2,
594  int iUpdateInterval, const C4Value & Data, int iRetries, int iBaseMode)
595 {
596  // Command
597  if (!szCommand)
598  {
599  return false;
600  }
601  long iCommand = CommandByName(FnStringPar(szCommand));
602  if (!iCommand)
603  {
604  return false;
605  }
606  // Special: convert iData to szText
607  C4String *szText = nullptr;
608  if (iCommand == C4CMD_Call)
609  {
610  szText=Data.getStr();
611  }
612  // Add
613  return Obj->AddCommand(iCommand,pTarget,Tx,iTy,iUpdateInterval,pTarget2,true,Data,true,iRetries,szText,iBaseMode);
614 }
615 
616 static C4Value FnGetCommand(C4Object *Obj, int iElement, int iCommandNum)
617 {
618  C4Command * Command = Obj->Command;
619  // Move through list to Command iCommandNum
620  while (Command && iCommandNum--)
621  {
622  Command = Command->Next;
623  }
624  // Object has no command or iCommandNum was to high or < 0
625  if (!Command)
626  {
627  return C4VNull;
628  }
629  // Return command element
630  switch (iElement)
631  {
632  case 0: // Name
633  return C4VString(CommandName(Command->Command));
634  case 1: // Target
635  return C4VObj(Command->Target);
636  case 2: // Tx
637  return Command->Tx;
638  case 3: // Ty
639  return C4VInt(Command->Ty);
640  case 4: // Target2
641  return C4VObj(Command->Target2);
642  case 5: // Data
643  return Command->Command == C4CMD_Call ? C4VString(Command->Text) : Command->Data;
644  }
645  // Undefined element
646  return C4VNull;
647 }
648 
649 static bool FnFinishCommand(C4Object *Obj, bool fSuccess, long iCommandNum)
650 {
651  C4Command * Command = Obj->Command;
652  // Move through list to Command iCommandNum
653  while (Command && iCommandNum--)
654  {
655  Command = Command->Next;
656  }
657  // Object has no command or iCommandNum was to high or < 0
658  if (!Command)
659  {
660  return false;
661  }
662  if (!fSuccess)
663  {
664  ++(Command->Failures);
665  }
666  else
667  {
668  Command->Finished = true;
669  }
670  return true;
671 }
672 
673 static C4String *FnGetAction(C4Object *Obj)
674 {
675  C4PropList* pActionDef = Obj->GetAction();
676  if (!pActionDef)
677  {
678  return String("Idle");
679  }
680  return String(pActionDef->GetName());
681 }
682 
683 static C4Object *FnGetActionTarget(C4Object *Obj, long target_index)
684 {
685  if (target_index==0) return Obj->Action.Target;
686  if (target_index==1) return Obj->Action.Target2;
687  return nullptr;
688 }
689 
690 static void FnSetActionTargets(C4Object *Obj, C4Object *pTarget1, C4Object *pTarget2)
691 {
692  // set targets
693  Obj->Action.Target = pTarget1;
694  Obj->Action.Target2 = pTarget2;
695 }
696 
697 static long FnGetDir(C4Object *Obj)
698 {
699  return Obj->Action.Dir;
700 }
701 
702 static bool FnGetEntrance(C4Object *Obj)
703 {
704  return Obj->EntranceStatus;
705 }
706 
707 static long FnGetPhase(C4Object *Obj)
708 {
709  return Obj->Action.Phase;
710 }
711 
712 static long FnGetEnergy(C4Object *Obj, bool fExact)
713 {
714  if (fExact)
715  {
716  return Obj->Energy;
717  }
718  else
719  {
720  return 100 * Obj->Energy / C4MaxPhysical;
721  }
722 }
723 
724 static long FnGetBreath(C4Object *Obj)
725 {
726  return Obj->Breath;
727 }
728 
729 static long FnGetMass(C4PropList * _this)
730 {
731  if (!Object(_this))
732  {
733  if (!_this || !_this->GetDef())
734  {
735  throw NeedNonGlobalContext("GetMass");
736  }
737  else
738  {
739  return _this->GetDef()->Mass;
740  }
741  }
742  else
743  {
744  return Object(_this)->Mass;
745  }
746 }
747 
748 static long FnGetRDir(C4Object *Obj, long iPrec)
749 {
750  if (!iPrec)
751  {
752  iPrec = 10;
753  }
754  return fixtoi(Obj->rdir, iPrec);
755 }
756 
757 static long FnGetXDir(C4Object *Obj, long iPrec)
758 {
759  if (!iPrec)
760  {
761  iPrec = 10;
762  }
763  return fixtoi(Obj->xdir, iPrec);
764 }
765 
766 static long FnGetYDir(C4Object *Obj, long iPrec)
767 {
768  if (!iPrec)
769  {
770  iPrec = 10;
771  }
772  return fixtoi(Obj->ydir, iPrec);
773 }
774 
775 static long FnGetR(C4Object *Obj)
776 {
777  // Adjust range
778  long iR = Obj->GetR();
779  while (iR > 180)
780  {
781  iR -= 360;
782  }
783  while (iR < -180)
784  {
785  iR += 360;
786  }
787  return iR;
788 }
789 
790 static long FnGetComDir(C4Object *Obj)
791 {
792  return Obj->Action.ComDir;
793 }
794 
795 static long FnGetVertexNum(C4Object *Obj)
796 {
797  return Obj->Shape.VtxNum;
798 }
799 
801 {
806 };
808 {
812 };
813 
814 static Nillable<long> FnGetVertex(C4Object *Obj, long iIndex, long iValueToGet)
815 {
816  if (Obj->Shape.VtxNum < 1)
817  {
818  return C4Void();
819  }
820  if (iIndex < 0 || iIndex >= Obj->Shape.VtxNum)
821  {
822  return C4Void();
823  }
824  iIndex=std::min<long>(iIndex,Obj->Shape.VtxNum-1);
825  switch (static_cast<VertexDataIndex>(iValueToGet))
826  {
827  case VTX_X:
828  return Obj->Shape.VtxX[iIndex];
829  case VTX_Y:
830  return Obj->Shape.VtxY[iIndex];
831  case VTX_CNAT:
832  return Obj->Shape.VtxCNAT[iIndex];
833  case VTX_Friction:
834  return Obj->Shape.VtxFriction[iIndex];
835  default:
836  DebugLog(FormatString("GetVertex: Unknown vertex attribute: %ld", iValueToGet).getData());
837  return C4Void();
838  }
839  // Impossible mayhem!
840  assert(!"FnGetVertex: unreachable code reached");
841  return C4Void();
842 }
843 
844 static bool FnSetVertex(C4Object *Obj, long iIndex, long iValueToSet, long iValue, long iOwnVertexMode)
845 {
846  // Own vertex mode?
847  if (iOwnVertexMode)
848  {
849  // Enter own custom vertex mode if not already set
850  if (!Obj->fOwnVertices)
851  {
852  Obj->Shape.CreateOwnOriginalCopy(Obj->Def->Shape);
853  Obj->fOwnVertices = true;
854  }
855  // Set vertices at end of buffer
856  iIndex += C4D_VertexCpyPos;
857  }
858  // Range check
859  if (!Inside<long>(iIndex,0,C4D_MaxVertex-1)) return false;
860  // Set desired value
861  switch (static_cast<VertexDataIndex>(iValueToSet))
862  {
863  case VTX_X:
864  Obj->Shape.VtxX[iIndex] = iValue;
865  break;
866  case VTX_Y:
867  Obj->Shape.VtxY[iIndex] = iValue;
868  break;
869  case VTX_CNAT:
870  Obj->Shape.VtxCNAT[iIndex] = iValue;
871  break;
872  case VTX_Friction:
873  Obj->Shape.VtxFriction[iIndex] = iValue;
874  break;
875  default:
876  DebugLogF("SetVertex: Unknown vertex attribute: %ld", iValueToSet);
877  return false;
878  }
879  // Vertex update desired?
880  if (iOwnVertexMode == VTX_SetPermanentUpd)
881  {
882  Obj->UpdateShape(true);
883  }
884  return true;
885 }
886 
887 static bool FnAddVertex(C4Object *Obj, long iX, long iY)
888 {
889  return !!Obj->Shape.AddVertex(iX, iY);
890 }
891 
892 static bool FnInsertVertex(C4Object *Obj, long iIndex, long iX, long iY)
893 {
894  return !!Obj->Shape.InsertVertex(iIndex, iX, iY);
895 }
896 
897 static bool FnRemoveVertex(C4Object *Obj, long iIndex)
898 {
899  return !!Obj->Shape.RemoveVertex(iIndex);
900 }
901 
902 static void FnSetContactDensity(C4Object *Obj, long iDensity)
903 {
904  Obj->Shape.ContactDensity = iDensity;
905 }
906 
907 static bool FnGetAlive(C4Object *Obj)
908 {
909  return Obj->GetAlive();
910 }
911 
912 static long FnGetOwner(C4Object *Obj)
913 {
914  return Obj->Owner;
915 }
916 
917 static long FnGetController(C4Object *Obj)
918 {
919  return Obj->Controller;
920 }
921 
922 static bool FnSetController(C4Object *Obj, long iNewController)
923 {
924  // validate player
925  if (iNewController != NO_OWNER && !ValidPlr(iNewController))
926  {
927  return false;
928  }
929  // Set controller
930  Obj->Controller = iNewController;
931  return true;
932 }
933 
934 static long FnGetKiller(C4Object *Obj)
935 {
936  return Obj->LastEnergyLossCausePlayer;
937 }
938 
939 static bool FnSetKiller(C4Object *Obj, long iNewKiller)
940 {
941  // Validate player
942  if (iNewKiller != NO_OWNER && !ValidPlr(iNewKiller))
943  {
944  return false;
945  }
946  // Set killer as last energy loss cause
947  Obj->LastEnergyLossCausePlayer = iNewKiller;
948  return true;
949 }
950 
951 static long FnGetCategory(C4PropList * _this)
952 {
953  if (!Object(_this))
954  {
955  if (!_this || !_this->GetDef())
956  {
957  throw NeedNonGlobalContext("GetCategory");
958  }
959  else
960  {
961  return _this->GetDef()->Category;
962  }
963  }
964  else
965  {
966  return Object(_this)->Category;
967  }
968 }
969 
970 static long FnGetOCF(C4Object *Obj)
971 {
972  return Obj->OCF;
973 }
974 
975 static long FnGetDamage(C4Object *Obj)
976 {
977  return Obj->Damage;
978 }
979 
980 static long FnGetValue(C4PropList * _this, C4Object *pInBase, long iForPlayer)
981 {
982  if (!Object(_this))
983  {
984  if (!_this || !_this->GetDef())
985  {
986  throw NeedNonGlobalContext("GetValue");
987  }
988  else
989  {
990  return _this->GetDef()->GetValue(pInBase, iForPlayer);
991  }
992  }
993  else
994  {
995  return Object(_this)->GetValue(pInBase, iForPlayer);
996  }
997 }
998 
999 static long FnGetRank(C4Object *Obj)
1000 {
1001  if (!Obj->Info)
1002  {
1003  return 0;
1004  }
1005  return Obj->Info->Rank;
1006 }
1007 
1008 static long FnGetActTime(C4Object *Obj)
1009 {
1010  return Obj->Action.Time;
1011 }
1012 
1013 static C4PropList* FnGetID(C4Object *Obj)
1014 {
1015  // Return id of object
1016  return Obj->GetPrototype();
1017 }
1018 
1019 static Nillable<C4Def*> FnGetMenu(C4Object *Obj)
1020 {
1021  if (Obj->Menu && Obj->Menu->IsActive())
1022  {
1023  return C4Id2Def(C4ID(Obj->Menu->GetIdentification()));
1024  }
1025  return C4Void();
1026 }
1027 
1028 static bool FnCreateMenu(C4Object *Obj, C4Def *pDef, C4Object *pCommandObj,
1029  long iExtra, C4String *szCaption, long iExtraData,
1030  long iStyle, bool fPermanent, C4ID idMenuID)
1031 {
1032  // Object menu: Validate object
1033  if (pCommandObj && !pCommandObj->Status)
1034  {
1035  return false;
1036  }
1037  // else scenario script callback: No command object OK
1038 
1039  // Create symbol
1040  C4FacetSurface fctSymbol;
1041  fctSymbol.Create(C4SymbolSize,C4SymbolSize);
1042  if (pDef)
1043  {
1044  pDef->Draw(fctSymbol);
1045  }
1046 
1047  // Clear any old menu, init new menu
1048  if (!Obj->CloseMenu(false))
1049  {
1050  return false;
1051  }
1052  if (!Obj->Menu)
1053  {
1054  Obj->Menu = new C4ObjectMenu;
1055  }
1056  else
1057  {
1058  Obj->Menu->ClearItems();
1059  }
1060  Obj->Menu->Init(fctSymbol, FnStringPar(szCaption), pCommandObj, iExtra, iExtraData, (idMenuID ? idMenuID : pDef ? pDef->id : C4ID::None).GetHandle(), iStyle, true);
1061 
1062  // Set permanent
1063  Obj->Menu->SetPermanent(fPermanent);
1064 
1065  return true;
1066 }
1067 
1068 const int C4MN_Add_ImgRank = 1,
1075  C4MN_Add_MaxImage = 127, // mask for param which decides what to draw as the menu symbol
1079 
1080 #ifndef _MSC_VER
1081 #define _snprintf snprintf
1082 #endif
1083 
1084 static bool FnAddMenuItem(C4Object *Obj, C4String * szCaption, C4String * szCommand, C4Def * pDef, int iCount, const C4Value & Parameter, C4String * szInfoCaption, int iExtra, const C4Value & XPar, const C4Value & XPar2)
1085 {
1086  if (!Obj->Menu)
1087  {
1088  return false;
1089  }
1090 
1091  char caption[256+1];
1092  char parameter[256+1];
1093  char dummy[256+1];
1094  char command[512+1];
1095  char command2[512+1];
1096  char infocaption[C4MaxTitle+1];
1097 
1098  // Get needed symbol size
1099  int iSymbolSize = Obj->Menu->GetSymbolSize();
1100 
1101  // Compose caption with def name
1102  if (szCaption)
1103  {
1104  const char * s = FnStringPar(szCaption);
1105  const char * sep = strstr(s, "%s");
1106  if (sep && pDef)
1107  {
1108  strncpy(caption, s, std::min<intptr_t>(sep - s,256));
1109  caption[std::min<intptr_t>(sep - s,256)] = 0;
1110  strncat(caption, pDef->GetName(), 256);
1111  strncat(caption, sep + 2, 256);
1112  }
1113  else
1114  {
1115  strncpy(caption, s, 256);
1116  caption[256] = 0;
1117  }
1118  }
1119  else
1120  {
1121  caption[0] = 0;
1122  }
1123 
1124  // Create string to include type-information in command
1125  switch (Parameter.GetType())
1126  {
1127  case C4V_Int:
1128  sprintf(parameter, "%d", Parameter.getInt());
1129  break;
1130  case C4V_Bool:
1131  SCopy(Parameter.getBool() ? "true" : "false", parameter);
1132  break;
1133  case C4V_PropList:
1134  if (Parameter.getPropList()->GetObject())
1135  {
1136  sprintf(parameter, "Object(%d)", Parameter.getPropList()->GetObject()->Number);
1137  }
1138  else if (Parameter.getPropList()->GetDef())
1139  {
1140  sprintf(parameter, R"(C4Id("%s"))", Parameter.getPropList()->GetDef()->id.ToString());
1141  }
1142  else
1143  {
1144  throw C4AulExecError("proplist as parameter to AddMenuItem");
1145  }
1146  break;
1147  case C4V_String:
1148  // note this breaks if there is '"' in the string.
1149  parameter[0] = '"';
1150  SCopy(Parameter.getStr()->GetCStr(), parameter + 1, sizeof(command)-3);
1151  SAppendChar('"', command);
1152  break;
1153  case C4V_Nil:
1154  SCopy("nil", parameter);
1155  break;
1156  case C4V_Array:
1157  // Arrays were never allowed, so tell the scripter
1158  throw C4AulExecError("array as parameter to AddMenuItem");
1159  default:
1160  return false;
1161  }
1162 
1163  // Own value
1164  bool fOwnValue = false;
1165  long iValue=0;
1166  if (iExtra & C4MN_Add_PassValue)
1167  {
1168  fOwnValue = true;
1169  iValue = XPar2.getInt();
1170  }
1171 
1172  // New Style: native script command
1173  size_t i = 0;
1174  for (; i < SLen(FnStringPar(szCommand)); i++)
1175  {
1176  if (!IsIdentifier(FnStringPar(szCommand)[i]))
1177  {
1178  break;
1179  }
1180  }
1181  if (i < SLen(FnStringPar(szCommand)))
1182  {
1183  // Search for "%d" an replace it by "%s" for insertion of formatted parameter
1184  SCopy(FnStringPar(szCommand), dummy, 256);
1185  auto* pFound = const_cast<char*>(SSearch(dummy, "%d"));
1186  if (pFound != nullptr)
1187  {
1188  *(pFound - 1) = 's';
1189  }
1190  // Compose left-click command
1191  sprintf(command, dummy, parameter, 0);
1192  // Compose right-click command
1193  sprintf(command2, dummy, parameter, 1);
1194  }
1195 
1196  // Old style: function name with id and parameter
1197  else
1198  {
1199  const char *szScriptCom = FnStringPar(szCommand);
1200  if (szScriptCom && *szScriptCom)
1201  {
1202  if (iExtra & C4MN_Add_PassValue)
1203  {
1204  // with value
1205  sprintf(command, "%s(%s,%s,0,%ld)", szScriptCom, pDef ? pDef->id.ToString() : "nil", parameter, iValue);
1206  sprintf(command2, "%s(%s,%s,1,%ld)", szScriptCom, pDef ? pDef->id.ToString() : "nil", parameter, iValue);
1207  }
1208  else
1209  {
1210  // without value
1211  sprintf(command, "%s(%s,%s)", szScriptCom, pDef ? pDef->id.ToString() : "nil", parameter);
1212  sprintf(command2, "%s(%s,%s,1)", szScriptCom, pDef ? pDef->id.ToString() : "nil", parameter);
1213  }
1214  }
1215  else
1216  {
1217  // no command
1218  *command = *command2 = '\0';
1219  }
1220  }
1221 
1222  // Info caption
1223  SCopy(FnStringPar(szInfoCaption), infocaption, C4MaxTitle);
1224 
1225  // Create symbol
1226  C4FacetSurface fctSymbol;
1227  C4DefGraphics* pGfx = nullptr;
1228  C4Object* pGfxObj = nullptr;
1229  switch (iExtra & C4MN_Add_MaxImage)
1230  {
1231  case C4MN_Add_ImgRank:
1232  {
1233  // symbol by rank
1234  C4Facet *pfctRankSym = &::GraphicsResource.fctRank;
1235  int32_t iRankSymNum = ::GraphicsResource.iNumRanks;
1236  if (pDef && pDef->pRankSymbols)
1237  {
1238  pfctRankSym = pDef->pRankSymbols;
1239  iRankSymNum = pDef->iNumRankSymbols;
1240  }
1241  C4RankSystem::DrawRankSymbol(&fctSymbol, iCount, pfctRankSym, iRankSymNum, true);
1242  iCount = 0;
1243  break;
1244  }
1245  case C4MN_Add_ImgIndexed:
1246  // draw indexed facet
1247  fctSymbol.Create(iSymbolSize,iSymbolSize);
1248  if (pDef)
1249  {
1250  pDef->Draw(fctSymbol, false, 0, nullptr, XPar.getInt());
1251  }
1252  break;
1253  case C4MN_Add_ImgObjRank:
1254  {
1255  // draw current gfx of XPar_C4V including rank
1256  if (!XPar.CheckConversion(C4V_Object))
1257  {
1258  return false;
1259  }
1260  C4Object *pGfxObj = XPar.getObj();
1261  if (pGfxObj && pGfxObj->Status)
1262  {
1263  // create graphics
1264  // get rank gfx
1265  C4Facet *pRankRes=&::GraphicsResource.fctRank;
1266  long iRankCnt=::GraphicsResource.iNumRanks;
1267  C4Def *pDef=pGfxObj->Def;
1268  if (pDef->pRankSymbols)
1269  {
1270  pRankRes=pDef->pRankSymbols;
1271  iRankCnt=pDef->iNumRankSymbols;
1272  }
1273  // context menu
1274  C4Facet fctRank;
1275  if (Obj->Menu->IsContextMenu())
1276  {
1277  // context menu entry: left object gfx
1278  long C4MN_SymbolSize = Obj->Menu->GetItemHeight();
1279  fctSymbol.Create(C4MN_SymbolSize * 2,C4MN_SymbolSize);
1280  fctSymbol.Wdt = C4MN_SymbolSize;
1281  pGfxObj->Def->Draw(fctSymbol, false, pGfxObj->Color, pGfxObj);
1282  // right of it the rank
1283  fctRank = fctSymbol;
1284  fctRank.X = C4MN_SymbolSize;
1285  fctSymbol.Wdt *= 2;
1286  }
1287  else
1288  {
1289  // regular menu: draw object picture
1290  fctSymbol.Create(iSymbolSize,iSymbolSize);
1291  pGfxObj->Def->Draw(fctSymbol, false, pGfxObj->Color, pGfxObj);
1292  // rank at top-right corner
1293  fctRank = fctSymbol;
1294  fctRank.X = fctRank.Wdt - pRankRes->Wdt;
1295  fctRank.Wdt = pRankRes->Wdt;
1296  fctRank.Hgt = pRankRes->Hgt;
1297  }
1298  // draw rank
1299  if (pGfxObj->Info)
1300  {
1301  C4Facet fctBackup = (const C4Facet &) fctSymbol;
1302  fctSymbol.Set(fctRank);
1303  C4RankSystem::DrawRankSymbol(&fctSymbol, pGfxObj->Info->Rank, pRankRes, iRankCnt, true);
1304  fctSymbol.Set(fctBackup);
1305  }
1306  }
1307  }
1308  break;
1309  case C4MN_Add_ImgObject:
1310  {
1311  // draw object picture
1312  if (!XPar.CheckConversion(C4V_Object))
1313  throw C4AulExecError(FormatString(R"(call to "%s" parameter %d: got "%s", but expected "%s"!)",
1314  "AddMenuItem", 8, XPar.GetTypeName(), GetC4VName(C4V_Object)
1315  ).getData());
1316  pGfxObj = XPar.getObj();
1317  }
1318  break;
1319 
1320  case C4MN_Add_ImgTextSpec:
1321  {
1322  C4Def* pDef = C4Id2Def(C4ID(std::string(caption)));
1323  if(pDef)
1324  {
1325  pGfx = &pDef->Graphics;
1326  }
1327  else
1328  {
1329  fctSymbol.Create(iSymbolSize,iSymbolSize);
1330  uint32_t dwClr = XPar.getInt();
1331  if (!szCaption || !Game.DrawTextSpecImage(fctSymbol, caption, nullptr, dwClr ? dwClr : 0xff))
1332  return false;
1333  }
1334  *caption = '\0';
1335  }
1336  break;
1337 
1339  {
1340  C4PropList *gfx_proplist = XPar.getPropList();
1341  fctSymbol.Create(iSymbolSize,iSymbolSize);
1342  if (!Game.DrawPropListSpecImage(fctSymbol, gfx_proplist))
1343  return false;
1344  }
1345  break;
1346 
1347  case C4MN_Add_ImgColor:
1348  // draw colored def facet
1349  fctSymbol.Create(iSymbolSize,iSymbolSize);
1350  if (pDef)
1351  pDef->Draw(fctSymbol, false, XPar.getInt());
1352  break;
1353 
1354  default:
1355  // default: by def, if it is not specifically NONE
1356  if (pDef)
1357  {
1358  fctSymbol.Create(iSymbolSize,iSymbolSize);
1359  pDef->Draw(fctSymbol);
1360  }
1361  else
1362  {
1363  // otherwise: Clear symbol!
1364  }
1365  break;
1366  }
1367 
1368  // Convert default zero count to no count
1369  if (iCount==0 && !(iExtra & C4MN_Add_ForceCount)) iCount=C4MN_Item_NoCount;
1370 
1371  // menuitems without commands are never selectable
1372  bool fIsSelectable = !!*command;
1373 
1374  // Add menu item
1375  if(pGfxObj)
1376  Obj->Menu->Add(caption,pGfxObj,command,iCount,nullptr,infocaption,pDef ? pDef->id : C4ID::None,command2,fOwnValue,iValue,fIsSelectable);
1377  else if(pGfx)
1378  Obj->Menu->Add(caption,pGfx,command,iCount,nullptr,infocaption,pDef ? pDef->id : C4ID::None,command2,fOwnValue,iValue,fIsSelectable);
1379  else
1380  Obj->Menu->Add(caption,fctSymbol,command,iCount,nullptr,infocaption,pDef ? pDef->id : C4ID::None,command2,fOwnValue,iValue,fIsSelectable);
1381 
1382  return true;
1383 }
1384 
1385 static bool FnSelectMenuItem(C4Object *Obj, long iItem)
1386 {
1387  if (!Obj->Menu)
1388  {
1389  return false;
1390  }
1391  return !!Obj->Menu->SetSelection(iItem, false, true);
1392 }
1393 
1394 static bool FnSetMenuDecoration(C4Object *Obj, C4ID idNewDeco)
1395 {
1396  if (!Obj->Menu)
1397  {
1398  return false;
1399  }
1401  if (!pNewDeco->SetByDef(idNewDeco))
1402  {
1403  delete pNewDeco;
1404  return false;
1405  }
1406  Obj->Menu->SetFrameDeco(pNewDeco);
1407  return true;
1408 }
1409 
1410 static bool FnSetMenuTextProgress(C4Object *Obj, long iNewProgress)
1411 {
1412  if (!Obj->Menu)
1413  {
1414  return false;
1415  }
1416  return Obj->Menu->SetTextProgress(iNewProgress, false);
1417 }
1418 
1419 
1420 // Check / Status
1421 
1422 static C4Object *FnContained(C4Object *Obj)
1423 {
1424  return Obj->Contained;
1425 }
1426 
1427 static C4Object *FnContents(C4Object *Obj, long index)
1428 {
1429  // Special: objects attaching to another object
1430  // cannot be accessed by FnContents
1431  C4Object *cobj;
1432  while ((cobj = Obj->Contents.GetObject(index++)))
1433  {
1434  if (cobj->GetProcedure() != DFA_ATTACH)
1435  {
1436  return cobj;
1437  }
1438  }
1439 
1440  return nullptr;
1441 }
1442 
1443 static bool FnShiftContents(C4Object *Obj, bool fShiftBack, C4Def * idTarget, bool fDoCalls)
1444 {
1445  // regular shift
1446  if (!idTarget)
1447  {
1448  return !!Obj->ShiftContents(fShiftBack, fDoCalls);
1449  }
1450  // check if ID is present within target
1451  C4Object *pNewFront = Obj->Contents.Find(idTarget);
1452  if (!pNewFront)
1453  {
1454  return false;
1455  }
1456  // select it
1457  Obj->DirectComContents(pNewFront, fDoCalls);
1458  // done, success
1459  return true;
1460 }
1461 
1462 static C4Object *FnScrollContents(C4Object *Obj)
1463 {
1464  C4Object *pMove = Obj->Contents.GetObject();
1465  if (pMove)
1466  {
1467  Obj->Contents.Remove(pMove);
1468  Obj->Contents.Add(pMove,C4ObjectList::stNone);
1469  }
1470 
1471  return Obj->Contents.GetObject();
1472 }
1473 
1474 static long FnContentsCount(C4Object *Obj, C4ID id)
1475 {
1476  return Obj->Contents.ObjectCount(id);
1477 }
1478 
1479 static C4Object *FnFindContents(C4Object *Obj, C4Def * c_id)
1480 {
1481  return Obj->Contents.Find(c_id);
1482 }
1483 
1484 static C4Object *FnFindOtherContents(C4Object *Obj, C4ID c_id)
1485 {
1486  return Obj->Contents.FindOther(c_id);
1487 }
1488 
1489 static bool FnActIdle(C4Object *Obj)
1490 {
1491  return !Obj->GetAction();
1492 }
1493 
1494 static bool FnStuck(C4Object *Obj, long off_x, long off_y)
1495 {
1496  return !!Obj->Shape.CheckContact(Obj->GetX() + off_x, Obj->GetY() + off_y);
1497 }
1498 
1499 static bool FnInLiquid(C4Object *Obj)
1500 {
1501  return Obj->InLiquid;
1502 }
1503 
1504 static bool FnOnFire(C4Object *Obj)
1505 {
1506  if (Obj->GetOnFire())
1507  {
1508  return true;
1509  }
1510  // check for effect
1511  if (!Obj->pEffects)
1512  {
1513  return false;
1514  }
1515  return !!Obj->pEffects->Get(C4Fx_AnyFire);
1516 }
1517 
1518 static C4Object *FnCreateContents(C4Object *Obj, C4PropList * PropList, Nillable<long> iCount)
1519 {
1520  // default amount parameter
1521  if (iCount.IsNil())
1522  {
1523  iCount = 1;
1524  }
1525  // create objects
1526  C4Object *pNewObj = nullptr;
1527  while (iCount-- > 0)
1528  {
1529  pNewObj = Obj->CreateContents(PropList);
1530  }
1531  // controller will automatically be set upon entrance
1532  // return last created
1533  return pNewObj;
1534 }
1535 
1536 static bool FnMakeCrewMember(C4Object *Obj, long iPlayer)
1537 {
1538  if (!ValidPlr(iPlayer))
1539  {
1540  return false;
1541  }
1542  return !!::Players.Get(iPlayer)->MakeCrewMember(Obj);
1543 }
1544 
1545 static bool FnGrabObjectInfo(C4Object *Obj, C4Object *pFrom)
1546 {
1547  // local call, safety
1548  if (!pFrom)
1549  {
1550  return false;
1551  }
1552  // grab info
1553  return !!Obj->GrabInfo(pFrom);
1554 }
1555 
1556 static bool FnSetCrewStatus(C4Object *Obj, long iPlr, bool fInCrew)
1557 {
1558  // validate player
1559  C4Player *pPlr = ::Players.Get(iPlr);
1560  if (!pPlr)
1561  {
1562  return false;
1563  }
1564  // set crew status
1565  return !!pPlr->SetObjectCrewStatus(Obj, fInCrew);
1566 }
1567 
1568 static long FnSetTransferZone(C4Object *Obj, long iX, long iY, long iWdt, long iHgt)
1569 {
1570  iX += Obj->GetX();
1571  iY += Obj->GetY();
1572  return Game.TransferZones.Set(iX, iY, iWdt, iHgt, Obj);
1573 }
1574 
1575 static long FnObjectDistance(C4PropList * _this, C4Object *pObj2, C4Object *pObj)
1576 {
1577  if (!pObj)
1578  {
1579  pObj = Object(_this);
1580  }
1581  if (!pObj || !pObj2)
1582  {
1583  return 0;
1584  }
1585  return Distance(pObj->GetX(), pObj->GetY(), pObj2->GetX(), pObj2->GetY());
1586 }
1587 
1588 static long FnObjectNumber(C4Object *Obj)
1589 {
1590  return Obj->Number;
1591  // See FnObject
1592 }
1593 
1594 static long FnShowInfo(C4Object *Obj, C4Object *pObj)
1595 {
1596  if (!pObj)
1597  {
1598  pObj = Obj;
1599  }
1600  if (!pObj)
1601  {
1602  return false;
1603  }
1604  return Obj->ActivateMenu(C4MN_Info,0,0,0,pObj);
1605 }
1606 
1607 static void FnSetMass(C4Object *Obj, long iValue)
1608 {
1609  Obj->OwnMass = iValue-Obj->Def->Mass;
1610  Obj->UpdateMass();
1611 }
1612 
1613 static long FnGetColor(C4Object *Obj)
1614 {
1615  return Obj->Color;
1616 }
1617 
1618 static void FnSetColor(C4Object *Obj, long iValue)
1619 {
1620  Obj->Color = iValue;
1621  Obj->UpdateGraphics(false);
1622  Obj->UpdateFace(false);
1623 }
1624 
1625 static void FnSetLightRange(C4Object *Obj, long iRange, Nillable<long> iFadeoutRange)
1626 {
1627  if (iFadeoutRange.IsNil())
1628  {
1629  if (iRange == 0)
1630  {
1631  iFadeoutRange = 0;
1632  }
1633  else
1634  {
1635  iFadeoutRange = C4FOW_DefLightFadeoutRangeX;
1636  }
1637  }
1638  // set range
1639  Obj->SetLightRange(iRange, iFadeoutRange);
1640 }
1641 
1642 static long FnGetLightColor(C4Object *Obj)
1643 {
1644  // get it
1645  return Obj->GetLightColor();
1646 }
1647 
1648 static void FnSetLightColor(C4Object *Obj, long iValue)
1649 {
1650  Obj->SetLightColor(iValue);
1651 }
1652 
1653 static void FnSetPicture(C4Object *Obj, long iX, long iY, long iWdt, long iHgt)
1654 {
1655  // set new picture rect
1656  Obj->PictureRect.Set(iX, iY, iWdt, iHgt);
1657 }
1658 
1659 static C4String *FnGetProcedure(C4Object *Obj)
1660 {
1661  // no action?
1662  C4PropList* pActionDef = Obj->GetAction();
1663  if (!pActionDef)
1664  {
1665  return nullptr;
1666  }
1667  // get proc
1668  return pActionDef->GetPropertyStr(P_Procedure);
1669 }
1670 
1671 static bool FnCheckVisibility(C4Object *Obj, int plr)
1672 {
1673  return Obj->IsVisible(plr, false);
1674 }
1675 
1676 static bool FnSetClrModulation(C4Object *Obj, Nillable<long> dwClr, long iOverlayID)
1677 {
1678  uint32_t clr = 0xffffffff;
1679  if (!dwClr.IsNil())
1680  {
1681  clr = dwClr;
1682  }
1683 
1684  // overlay?
1685  if (iOverlayID)
1686  {
1687  C4GraphicsOverlay *pOverlay = Obj->GetGraphicsOverlay(iOverlayID, false);
1688  if (!pOverlay)
1689  {
1690  DebugLogF("SetClrModulation: Overlay %d not defined for object %d (%s)", (int) iOverlayID, (int) Obj->Number, Obj->GetName());
1691  return false;
1692  }
1693  pOverlay->SetClrModulation(clr);
1694  // C4GraphicsOverlay Does not have an StdMeshInstance (yet), no need to
1695  // update faceordering
1696  }
1697  else
1698  {
1699  // set it
1700  Obj->ColorMod=clr;
1701  if (Obj->pMeshInstance)
1702  {
1704  }
1705  }
1706  // success
1707  return true;
1708 }
1709 
1710 static Nillable<long> FnGetClrModulation(C4Object *Obj, long iOverlayID)
1711 {
1712  // overlay?
1713  if (iOverlayID)
1714  {
1715  C4GraphicsOverlay *pOverlay = Obj->GetGraphicsOverlay(iOverlayID, false);
1716  if (!pOverlay)
1717  {
1718  DebugLogF("GetClrModulation: Overlay %d not defined for object %d (%s)", (int) iOverlayID, (int) Obj->Number, Obj->GetName());
1719  return C4Void();
1720  }
1721  return pOverlay->GetClrModulation();
1722  }
1723  else
1724  {
1725  // get it
1726  return Obj->ColorMod;
1727  }
1728 }
1729 
1730 static bool FnCloseMenu(C4Object *Obj)
1731 {
1732  return !!Obj->CloseMenu(true);
1733 }
1734 
1735 static Nillable<long> FnGetMenuSelection(C4Object *Obj)
1736 {
1737  if (!Obj->Menu || !Obj->Menu->IsActive())
1738  {
1739  return C4Void();
1740  }
1741  return Obj->Menu->GetSelection();
1742 }
1743 
1744 static bool FnCanConcatPictureWith(C4Object *Obj, C4Object *pObj)
1745 {
1746  // safety
1747  if (!Obj->Status || !pObj)
1748  {
1749  return false;
1750  }
1751  // Call the function in the object
1752  return Obj->CanConcatPictureWith(pObj);
1753 }
1754 
1755 static bool FnSetGraphics(C4Object *Obj, C4String *pGfxName, C4Def *pSrcDef, long iOverlayID, long iOverlayMode, C4String *pAction, long dwBlitMode, C4Object *pOverlayObject)
1756 {
1757  // safety
1758  if (!Obj->Status)
1759  {
1760  return false;
1761  }
1762  // setting overlay?
1763  if (iOverlayID)
1764  {
1765  // any overlays must be positive for now
1766  if (iOverlayID < 0)
1767  {
1768  Log("SetGraphics: Background overlays not implemented!");
1769  return false;
1770  }
1771  // deleting overlay?
1772  C4DefGraphics *pGrp = nullptr;
1773  if (iOverlayMode == C4GraphicsOverlay::MODE_Object || iOverlayMode == C4GraphicsOverlay::MODE_Rank || iOverlayMode == C4GraphicsOverlay::MODE_ObjectPicture)
1774  {
1775  if (!pOverlayObject)
1776  {
1777  return Obj->RemoveGraphicsOverlay(iOverlayID);
1778  }
1779  }
1780  else
1781  {
1782  if (!pSrcDef)
1783  {
1784  return Obj->RemoveGraphicsOverlay(iOverlayID);
1785  }
1786  pGrp = pSrcDef->Graphics.Get(FnStringPar(pGfxName));
1787  if (!pGrp)
1788  {
1789  return false;
1790  }
1791  }
1792  // adding/setting
1793  C4GraphicsOverlay *pOverlay = Obj->GetGraphicsOverlay(iOverlayID, true);
1794  switch (iOverlayMode)
1795  {
1797  pOverlay->SetAsBase(pGrp, dwBlitMode);
1798  break;
1799 
1801  pOverlay->SetAsAction(pGrp, FnStringPar(pAction), dwBlitMode);
1802  break;
1803 
1805  pOverlay->SetAsIngamePicture(pGrp, dwBlitMode);
1806  break;
1807 
1809  pOverlay->SetAsPicture(pGrp, dwBlitMode);
1810  break;
1811 
1813  if (pOverlayObject && !pOverlayObject->Status) pOverlayObject = nullptr;
1814  pOverlay->SetAsObject(pOverlayObject, dwBlitMode);
1815  break;
1816 
1818  pOverlay->SetAsExtraGraphics(pGrp, dwBlitMode);
1819  break;
1820 
1822  if (pOverlayObject && !pOverlayObject->Status) pOverlayObject = nullptr;
1823  pOverlay->SetAsRank(dwBlitMode, pOverlayObject);
1824  break;
1825 
1827  if (pOverlayObject && !pOverlayObject->Status) pOverlayObject = nullptr;
1828  pOverlay->SetAsObjectPicture(pOverlayObject, dwBlitMode);
1829  break;
1830 
1831  default:
1832  DebugLog("SetGraphics: Invalid overlay mode");
1833  pOverlay->SetAsBase(nullptr, 0); // make invalid, so it will be removed
1834  break;
1835  }
1836  // remove if invalid
1837  if (!pOverlay->IsValid(Obj))
1838  {
1839  Obj->RemoveGraphicsOverlay(iOverlayID);
1840  return false;
1841  }
1842  // Okay, valid overlay set!
1843  return true;
1844  }
1845  // no overlay: Base graphics
1846  // set graphics - pSrcDef==nullptr defaults to pObj->pDef
1847  return Obj->SetGraphics(FnStringPar(pGfxName), pSrcDef);
1848 }
1849 
1850 static long FnGetDefBottom(C4PropList * _this)
1851 {
1852  if (!_this || !_this->GetDef())
1853  {
1854  throw NeedNonGlobalContext("GetDefBottom");
1855  }
1856 
1857  C4Object *obj = Object(_this);
1858  C4Def *def = _this->GetDef();
1859  assert(!obj || obj->Def == def);
1860 
1861  if (obj)
1862  {
1863  return obj->GetY() + obj->Shape.GetBottom();
1864  }
1865  else if (def)
1866  {
1867  return def->Shape.GetBottom();
1868  }
1869  else
1870  {
1871  return 0;
1872  }
1873 }
1874 
1875 static bool FnSetMenuSize(C4Object *Obj, long iCols, long iRows)
1876 {
1877  // get menu
1878  C4Menu *pMnu=Obj->Menu;
1879  if (!pMnu || !pMnu->IsActive())
1880  {
1881  return false;
1882  }
1883  pMnu->SetSize(Clamp<long>(iCols, 0, 50), Clamp<long>(iRows, 0, 50));
1884  return true;
1885 }
1886 
1887 static bool FnGetCrewEnabled(C4Object *Obj)
1888 {
1889  // return status
1890  return !Obj->CrewDisabled;
1891 }
1892 
1893 static void FnSetCrewEnabled(C4Object *Obj, bool fEnabled)
1894 {
1895  bool change = (Obj->CrewDisabled == fEnabled) ? true : false;
1896 
1897  // set status
1898  Obj->CrewDisabled=!fEnabled;
1899  // deselect
1900  if (!fEnabled)
1901  {
1902  C4Player *pOwner;
1903  if ((pOwner=::Players.Get(Obj->Owner)))
1904  {
1905  // if viewed player cursor gets deactivated and no new cursor is found, follow the old in target mode
1906  bool fWasCursorMode = (pOwner->ViewMode == C4PVM_Cursor);
1907  if (pOwner->Cursor==Obj)
1908  {
1909  pOwner->AdjustCursorCommand();
1910  }
1911  if (!pOwner->ViewCursor && !pOwner->Cursor && fWasCursorMode)
1912  {
1913  pOwner->SetViewMode(C4PVM_Target, Obj);
1914  }
1915  }
1916  }
1917 
1918  // call to crew
1919  if (change)
1920  {
1921  if (fEnabled)
1922  {
1923  Obj->Call(PSF_CrewEnabled);
1924  }
1925  else
1926  {
1927  Obj->Call(PSF_CrewDisabled);
1928  }
1929  }
1930 }
1931 
1932 static void FnDoCrewExp(C4Object *Obj, long iChange)
1933 {
1934  // do exp
1935  Obj->DoExperience(iChange);
1936 }
1937 
1938 static bool FnClearMenuItems(C4Object *Obj)
1939 {
1940  // check menu
1941  if (!Obj->Menu)
1942  {
1943  return false;
1944  }
1945  // clear the items
1946  Obj->Menu->ClearItems();
1947  // success
1948  return true;
1949 }
1950 
1951 static C4Object *FnGetObjectLayer(C4Object *Obj)
1952 {
1953  // get layer object
1954  return Obj->Layer;
1955 }
1956 
1957 static void FnSetObjectLayer(C4Object *Obj, C4Object *pNewLayer)
1958 {
1959  // set layer object
1960  Obj->Layer = pNewLayer;
1961  // set for all contents as well
1962  for (C4Object* contentObj : Obj->Contents)
1963  {
1964  if (contentObj && contentObj->Status)
1965  {
1966  contentObj->Layer = pNewLayer;
1967  }
1968  }
1969 }
1970 
1971 static void FnSetShape(C4Object *Obj, long iX, long iY, long iWdt, long iHgt)
1972 {
1973  // update shape
1974  Obj->Shape.x = iX;
1975  Obj->Shape.y = iY;
1976  Obj->Shape.Wdt = iWdt;
1977  Obj->Shape.Hgt = iHgt;
1978  // section list needs refresh
1979  Obj->UpdatePos();
1980 }
1981 
1982 static bool FnSetObjDrawTransform(C4Object *Obj, long iA, long iB, long iC, long iD, long iE, long iF, long iOverlayID)
1983 {
1984  C4DrawTransform *pTransform;
1985  // overlay?
1986  if (iOverlayID)
1987  {
1988  // set overlay transform
1989  C4GraphicsOverlay *pOverlay = Obj->GetGraphicsOverlay(iOverlayID, false);
1990  if (!pOverlay)
1991  {
1992  return false;
1993  }
1994  pTransform = pOverlay->GetTransform();
1995  }
1996  else
1997  {
1998  // set base transform
1999  pTransform = Obj->pDrawTransform;
2000  // del transform?
2001  if (!iB && !iC && !iD && !iF && iA==iE && (!iA || iA==1000))
2002  {
2003  // identity/0 and no transform defined: nothing to do
2004  if (!pTransform)
2005  {
2006  return true;
2007  }
2008  // transform has no flipdir?
2009  if (pTransform->FlipDir == 1)
2010  {
2011  // kill identity-transform, then
2012  delete pTransform;
2013  Obj->pDrawTransform = nullptr;
2014  return true;
2015  }
2016  // flipdir must remain: set identity
2017  pTransform->Set(1,0,0,0,1,0,0,0,1);
2018  return true;
2019  }
2020  // create draw transform if not already present
2021  if (!pTransform)
2022  {
2023  pTransform = Obj->pDrawTransform = new C4DrawTransform();
2024  }
2025  }
2026  // assign values
2027  pTransform->Set((float) iA/1000, (float) iB/1000, (float) iC/1000, (float) iD/1000, (float) iE/1000, (float) iF/1000, 0, 0, 1);
2028  // done, success
2029  return true;
2030 }
2031 
2032 static bool FnSetObjDrawTransform2(C4Object *Obj, long iA, long iB, long iC, long iD, long iE, long iF, long iG, long iH, long iI, long iOverlayID)
2033 {
2034  // local call / safety
2035  C4Object * pObj = Obj;
2036  C4DrawTransform *pTransform;
2037  // overlay?
2038  if (iOverlayID)
2039  {
2040  // set overlay transform
2041  C4GraphicsOverlay *pOverlay = pObj->GetGraphicsOverlay(iOverlayID, false);
2042  if (!pOverlay)
2043  {
2044  return false;
2045  }
2046  pTransform = pOverlay->GetTransform();
2047  }
2048  else
2049  {
2050  // set base transform
2051  pTransform = pObj->pDrawTransform;
2052  // create draw transform if not already present
2053  if (!pTransform)
2054  {
2055  pTransform = pObj->pDrawTransform = new C4DrawTransform(1);
2056  }
2057  }
2058  // assign values
2059 #define L2F(l) ((float)l/1000)
2060  C4BltTransform matrix;
2061  matrix.Set(L2F(iA), L2F(iB), L2F(iC), L2F(iD), L2F(iE), L2F(iF), L2F(iG), L2F(iH), L2F(iI));
2062  *pTransform *= matrix;
2063 #undef L2F
2064  // done, success
2065  return true;
2066 }
2067 
2068 static bool FnSetObjectStatus(C4Object *Obj, long iNewStatus, bool fClearPointers)
2069 {
2070  // local call / safety
2071  if (!Obj->Status)
2072  {
2073  return false;
2074  }
2075  // no change
2076  if (Obj->Status == iNewStatus)
2077  {
2078  return true;
2079  }
2080  // set new status
2081  switch (iNewStatus)
2082  {
2083  case C4OS_NORMAL:
2084  return Obj->StatusActivate();
2085  case C4OS_INACTIVE:
2086  return Obj->StatusDeactivate(fClearPointers);
2087  default:
2088  return false; // status unknown
2089  }
2090 }
2091 
2092 static long FnGetObjectStatus(C4Object *Obj)
2093 {
2094  return Obj->Status;
2095 }
2096 
2097 static bool FnAdjustWalkRotation(C4Object *Obj, long iRangeX, long iRangeY, long iSpeed)
2098 {
2099  // must be rotateable and attached to solid ground
2100  if (!Obj->Def->Rotateable || (~Obj->Action.t_attach & CNAT_Bottom) || Obj->Shape.AttachMat == MNone)
2101  {
2102  return false;
2103  }
2104  // adjust rotation
2105  return Obj->AdjustWalkRotation(iRangeX, iRangeY, iSpeed);
2106 }
2107 
2108 static long FnGetContact(C4Object *Obj, long iVertex, long dwCheck)
2109 {
2110  // vertex not specified: check all
2111  if (iVertex == -1)
2112  {
2113  long iResult = 0;
2114  for (int i=0; i<Obj->Shape.VtxNum; ++i)
2115  {
2116  iResult |= Obj->Shape.GetVertexContact(i, dwCheck, Obj->GetX(), Obj->GetY());
2117  }
2118  return iResult;
2119  }
2120  // vertex specified: check it
2121  if (!Inside<long>(iVertex, 0, Obj->Shape.VtxNum-1))
2122  {
2123  return 0;
2124  }
2125  return Obj->Shape.GetVertexContact(iVertex, dwCheck, Obj->GetX(), Obj->GetY());
2126 }
2127 
2128 static long FnSetObjectBlitMode(C4Object *Obj, long dwNewBlitMode, long iOverlayID)
2129 {
2130  // overlay?
2131  if (iOverlayID)
2132  {
2133  C4GraphicsOverlay *pOverlay = Obj->GetGraphicsOverlay(iOverlayID, false);
2134  if (!pOverlay)
2135  {
2136  DebugLogF("SetObjectBlitMode: Overlay %d not defined for object %d (%s)", (int) iOverlayID, (int) Obj->Number, Obj->GetName());
2137  return false;
2138  }
2139  pOverlay->SetBlitMode(dwNewBlitMode);
2140  return true;
2141  }
2142  // get prev blit mode
2143  DWORD dwPrevMode = Obj->BlitMode;
2144  // iNewBlitMode = 0: reset to definition default
2145  if (!dwNewBlitMode)
2146  {
2147  Obj->BlitMode = Obj->Def->BlitMode;
2148  }
2149  else
2150  {
2151  // otherwise, set the desired value
2152  // also ensure that the custom flag is set
2153  Obj->BlitMode = dwNewBlitMode | C4GFXBLIT_CUSTOM;
2154  }
2155  // return previous value
2156  return dwPrevMode;
2157 }
2158 
2159 static Nillable<long> FnGetObjectBlitMode(C4Object *Obj, long iOverlayID)
2160 {
2161  // overlay?
2162  if (iOverlayID)
2163  {
2164  C4GraphicsOverlay *pOverlay = Obj->GetGraphicsOverlay(iOverlayID, false);
2165  if (!pOverlay)
2166  {
2167  DebugLogF("SetObjectBlitMode: Overlay %d not defined for object %d (%s)", (int) iOverlayID, (int) Obj->Number, Obj->GetName());
2168  return C4Void();
2169  }
2170  return pOverlay->GetBlitMode();
2171  }
2172  // get blitting mode
2173  return Obj->BlitMode;
2174 }
2175 
2176 static long FnGetUnusedOverlayID(C4Object *Obj, long iBaseIndex)
2177 {
2178  // safety
2179  if (!iBaseIndex)
2180  {
2181  return 0;
2182  }
2183  // find search first unused index from there on
2184  int iSearchDir = (iBaseIndex < 0) ? -1 : 1;
2185  while (Obj->GetGraphicsOverlay(iBaseIndex, false))
2186  {
2187  iBaseIndex += iSearchDir;
2188  }
2189  return iBaseIndex;
2190 }
2191 
2192 static Nillable<int> FnPlayAnimation(C4Object *Obj, C4String *szAnimation, int iSlot, C4ValueArray* PositionProvider, Nillable<C4ValueArray*> WeightProvider, Nillable<int> iSibling, Nillable<int> iAttachNumber)
2193 {
2194  if (!Obj)
2195  {
2196  return C4Void();
2197  }
2198  if (!Obj->pMeshInstance)
2199  {
2200  return C4Void();
2201  }
2202  if (iSlot == 0)
2203  {
2204  return C4Void(); // Reserved for ActMap animations
2205  }
2206  if (!PositionProvider)
2207  {
2208  return C4Void();
2209  }
2210  // If no weight provider is passed, this animation should be played exclusively.
2211  bool stop_previous_animations = WeightProvider.IsNil();
2212  // Exclusive mode cannot work with a sibling
2213  if (!iSibling.IsNil() && stop_previous_animations)
2214  {
2215  return C4Void();
2216  }
2217 
2218  StdMeshInstance* Instance = Obj->pMeshInstance;
2219  if (!iAttachNumber.IsNil())
2220  {
2221  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2222  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2223  if (!Attached || !Attached->OwnChild)
2224  {
2225  return C4Void();
2226  }
2227  Instance = Attached->Child;
2228  }
2229 
2230  StdMeshInstance::AnimationNode* s_node = nullptr;
2231  if (!iSibling.IsNil())
2232  {
2233  s_node = Instance->GetAnimationNodeByNumber(iSibling);
2234  if (!s_node || s_node->GetSlot() != iSlot)
2235  {
2236  return C4Void();
2237  }
2238  }
2239 
2240  const StdMeshAnimation* animation = Instance->GetMesh().GetSkeleton().GetAnimationByName(szAnimation->GetData());
2241  if (!animation)
2242  {
2243  return C4Void();
2244  }
2245 
2246  StdMeshInstance::ValueProvider* p_provider = CreateValueProviderFromArray(Obj, *PositionProvider, animation);
2247  StdMeshInstance::ValueProvider* w_provider;
2248  if (stop_previous_animations)
2249  {
2250  w_provider = new C4ValueProviderConst(Fix1);
2251  }
2252  else
2253  {
2254  w_provider = CreateValueProviderFromArray(Obj, *WeightProvider);
2255  }
2256  if (!p_provider || !w_provider)
2257  {
2258  delete p_provider;
2259  delete w_provider;
2260  return C4Void();
2261  }
2262 
2263  StdMeshInstance::AnimationNode* n_node = Instance->PlayAnimation(*animation, iSlot, s_node, p_provider, w_provider, stop_previous_animations);
2264  if (!n_node)
2265  {
2266  return C4Void();
2267  }
2268 
2269  return n_node->GetNumber();
2270 }
2271 
2272 static Nillable<int> FnTransformBone(C4Object *Obj, C4String *szBoneName, C4ValueArray* Transformation, int iSlot, C4ValueArray* WeightProvider, Nillable<int> iSibling, Nillable<int> iAttachNumber)
2273 {
2274  if (!Obj)
2275  {
2276  return C4Void();
2277  }
2278  if (!Obj->pMeshInstance)
2279  {
2280  return C4Void();
2281  }
2282  if (iSlot == 0)
2283  {
2284  return C4Void(); // Reserved for ActMap animations
2285  }
2286  if (!Transformation)
2287  {
2288  return C4Void();
2289  }
2290  if (!WeightProvider)
2291  {
2292  return C4Void();
2293  }
2294 
2295  StdMeshInstance* Instance = Obj->pMeshInstance;
2296  if (!iAttachNumber.IsNil())
2297  {
2298  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2299  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2300  if (!Attached || !Attached->OwnChild)
2301  {
2302  return C4Void();
2303  }
2304  Instance = Attached->Child;
2305  }
2306 
2307  StdMeshInstance::AnimationNode* s_node = nullptr;
2308  if (!iSibling.IsNil())
2309  {
2310  s_node = Instance->GetAnimationNodeByNumber(iSibling);
2311  if (!s_node || s_node->GetSlot() != iSlot)
2312  {
2313  return C4Void();
2314  }
2315  }
2316 
2317  const StdMeshBone* bone = Instance->GetMesh().GetSkeleton().GetBoneByName(szBoneName->GetData());
2318  if (!bone)
2319  {
2320  return C4Void();
2321  }
2322 
2323  StdMeshInstance::ValueProvider* w_provider = CreateValueProviderFromArray(Obj, *WeightProvider);
2324  if (!w_provider)
2325  {
2326  return C4Void();
2327  }
2328 
2329  StdMeshMatrix matrix;
2330  if (!C4ValueToMatrix(*Transformation, &matrix))
2331  {
2332  throw C4AulExecError("TransformBone: Transformation is not a valid 3x4 matrix");
2333  }
2334 
2335  // For bone transformations we cannot use general matrix transformations, but we use decomposed
2336  // translate, scale and rotation components (represented by the StdMeshTransformation class). This
2337  // is less generic since it does not support skewing.
2338  // Still, in the script API we want to expose a matrix parameter so that the convenient Trans_*
2339  // functions can be used. We decompose the passed matrix at this point. If the matrix indeed has
2340  // skewing components, the results will probably look strange since the decomposition would yield
2341  // bogus values, however I don't think that's a practical use case. In the worst case we could add
2342  // a check here and return nil if the matrix cannot be decomposed.
2343  StdMeshTransformation trans = matrix.Decompose();
2344 
2345  StdMeshInstance::AnimationNode* n_node = Instance->PlayAnimation(bone, trans, iSlot, s_node, w_provider, false);
2346  if (!n_node)
2347  {
2348  return C4Void();
2349  }
2350 
2351  return n_node->GetNumber();
2352 }
2353 
2354 static bool FnStopAnimation(C4Object *Obj, Nillable<int> iAnimationNumber, Nillable<int> iAttachNumber)
2355 {
2356  if (!Obj)
2357  {
2358  return false;
2359  }
2360  if (!Obj->pMeshInstance)
2361  {
2362  return false;
2363  }
2364  if (iAnimationNumber.IsNil())
2365  {
2366  return false; // distinguish nil from 0
2367  }
2368 
2369  StdMeshInstance* Instance = Obj->pMeshInstance;
2370  if (!iAttachNumber.IsNil())
2371  {
2372  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2373  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2374  if (!Attached || !Attached->OwnChild)
2375  {
2376  return false;
2377  }
2378  Instance = Attached->Child;
2379  }
2380 
2381  StdMeshInstance::AnimationNode* node = Instance->GetAnimationNodeByNumber(iAnimationNumber);
2382  // slot 0 is reserved for ActMap animations
2383  if (!node || node->GetSlot() == 0)
2384  {
2385  return false;
2386  }
2387  Instance->StopAnimation(node);
2388  return true;
2389 }
2390 
2391 static Nillable<int> FnGetRootAnimation(C4Object *Obj, int iSlot, Nillable<int> iAttachNumber)
2392 {
2393  if (!Obj)
2394  {
2395  return C4Void();
2396  }
2397  if (!Obj->pMeshInstance)
2398  {
2399  return C4Void();
2400  }
2401 
2402  StdMeshInstance* Instance = Obj->pMeshInstance;
2403  if (!iAttachNumber.IsNil())
2404  {
2405  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2406  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2407  if (!Attached || !Attached->OwnChild)
2408  {
2409  return C4Void();
2410  }
2411  Instance = Attached->Child;
2412  }
2413 
2415  if (!node)
2416  {
2417  return C4Void();
2418  }
2419  return node->GetNumber();
2420 }
2421 
2422 static Nillable<C4ValueArray*> FnGetAnimationList(C4PropList* _this, Nillable<int> iAttachNumber)
2423 {
2424  C4Object *Obj = Object(_this);
2425  const StdMeshSkeleton* skeleton;
2426  if (!Obj)
2427  {
2428  if (!_this || !_this->GetDef())
2429  {
2430  throw NeedNonGlobalContext("GetAnimationList");
2431  }
2432  C4Def *def = _this->GetDef();
2433  if (!def->Graphics.IsMesh())
2434  {
2435  return C4Void();
2436  }
2437 
2438  skeleton = &def->Graphics.Mesh->GetSkeleton();
2439  }
2440  else
2441  {
2442  if (!Obj)
2443  {
2444  return C4Void();
2445  }
2446  if (!Obj->pMeshInstance)
2447  {
2448  return C4Void();
2449  }
2450 
2451  StdMeshInstance* Instance = Obj->pMeshInstance;
2452  if (!iAttachNumber.IsNil())
2453  {
2454  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2455  // OwnChild is set if an object's instance is attached. In that case the animation list should be obtained directly on that object.
2456  if (!Attached || !Attached->OwnChild)
2457  {
2458  return C4Void();
2459  }
2460  Instance = Attached->Child;
2461  }
2462 
2463  skeleton = &Instance->GetMesh().GetSkeleton();
2464  }
2465 
2466  const std::vector<const StdMeshAnimation*> animations = skeleton->GetAnimations();
2467 
2468  C4ValueArray* retval = new C4ValueArray(animations.size());
2469  for(unsigned int i = 0; i < animations.size(); ++i)
2470  {
2471  (*retval)[i] = C4VString(animations[i]->Name);
2472  }
2473  return retval;
2474 }
2475 
2476 static Nillable<int> FnGetAnimationLength(C4Object *Obj, C4String *szAnimation, Nillable<int> iAttachNumber)
2477 {
2478  if (!Obj)
2479  {
2480  return C4Void();
2481  }
2482  if (!Obj->pMeshInstance)
2483  {
2484  return C4Void();
2485  }
2486 
2487  StdMeshInstance* Instance = Obj->pMeshInstance;
2488  if (!iAttachNumber.IsNil())
2489  {
2490  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2491  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2492  if (!Attached || !Attached->OwnChild)
2493  {
2494  return C4Void();
2495  }
2496  Instance = Attached->Child;
2497  }
2498 
2499  const StdMeshAnimation* animation = Instance->GetMesh().GetSkeleton().GetAnimationByName(szAnimation->GetData());
2500  if (!animation)
2501  {
2502  return C4Void();
2503  }
2504  return fixtoi(ftofix(animation->Length), 1000); // sync critical!
2505 }
2506 
2507 static Nillable<C4String*> FnGetAnimationName(C4Object *Obj, Nillable<int> iAnimationNumber, Nillable<int> iAttachNumber)
2508 {
2509  if (!Obj)
2510  {
2511  return C4Void();
2512  }
2513  if (!Obj->pMeshInstance)
2514  {
2515  return C4Void();
2516  }
2517  if (iAnimationNumber.IsNil())
2518  {
2519  return C4Void(); // distinguish nil from 0
2520  }
2521 
2522  StdMeshInstance* Instance = Obj->pMeshInstance;
2523  if (!iAttachNumber.IsNil())
2524  {
2525  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2526  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2527  if (!Attached || !Attached->OwnChild)
2528  {
2529  return C4Void();
2530  }
2531  Instance = Attached->Child;
2532  }
2533 
2534  StdMeshInstance::AnimationNode* node = Instance->GetAnimationNodeByNumber(iAnimationNumber);
2535  if (!node || node->GetType() != StdMeshInstance::AnimationNode::LeafNode)
2536  {
2537  return C4Void();
2538  }
2539  return String(node->GetAnimation()->Name.getData());
2540 }
2541 
2542 static Nillable<int> FnGetAnimationPosition(C4Object *Obj, Nillable<int> iAnimationNumber, Nillable<int> iAttachNumber)
2543 {
2544  if (!Obj)
2545  {
2546  return C4Void();
2547  }
2548  if (!Obj->pMeshInstance)
2549  {
2550  return C4Void();
2551  }
2552  if (iAnimationNumber.IsNil())
2553  {
2554  return C4Void(); // distinguish nil from 0
2555  }
2556 
2557  StdMeshInstance* Instance = Obj->pMeshInstance;
2558  if (!iAttachNumber.IsNil())
2559  {
2560  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2561  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2562  if (!Attached || !Attached->OwnChild)
2563  {
2564  return C4Void();
2565  }
2566  Instance = Attached->Child;
2567  }
2568 
2569  StdMeshInstance::AnimationNode* node = Instance->GetAnimationNodeByNumber(iAnimationNumber);
2570  if (!node || node->GetType() != StdMeshInstance::AnimationNode::LeafNode)
2571  {
2572  return C4Void();
2573  }
2574  return fixtoi(node->GetPosition(), 1000);
2575 }
2576 
2577 static Nillable<int> FnGetAnimationWeight(C4Object *Obj, Nillable<int> iAnimationNumber, Nillable<int> iAttachNumber)
2578 {
2579  if (!Obj)
2580  {
2581  return C4Void();
2582  }
2583  if (!Obj->pMeshInstance)
2584  {
2585  return C4Void();
2586  }
2587  if (iAnimationNumber.IsNil())
2588  {
2589  return C4Void(); // distinguish nil from 0
2590  }
2591 
2592  StdMeshInstance* Instance = Obj->pMeshInstance;
2593  if (!iAttachNumber.IsNil())
2594  {
2595  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2596  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2597  if (!Attached || !Attached->OwnChild)
2598  {
2599  return C4Void();
2600  }
2601  Instance = Attached->Child;
2602  }
2603 
2604  StdMeshInstance::AnimationNode* node = Instance->GetAnimationNodeByNumber(iAnimationNumber);
2606  {
2607  return C4Void();
2608  }
2609  return fixtoi(node->GetWeight(), 1000);
2610 }
2611 
2612 static bool FnSetAnimationPosition(C4Object *Obj, Nillable<int> iAnimationNumber, C4ValueArray* PositionProvider, Nillable<int> iAttachNumber)
2613 {
2614  if (!Obj)
2615  {
2616  return false;
2617  }
2618  if (!Obj->pMeshInstance)
2619  {
2620  return false;
2621  }
2622  if (iAnimationNumber.IsNil())
2623  {
2624  return false; // distinguish nil from 0
2625  }
2626 
2627  StdMeshInstance* Instance = Obj->pMeshInstance;
2628  if (!iAttachNumber.IsNil())
2629  {
2630  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2631  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2632  if (!Attached || !Attached->OwnChild)
2633  {
2634  return false;
2635  }
2636  Instance = Attached->Child;
2637  }
2638 
2639  StdMeshInstance::AnimationNode* node = Instance->GetAnimationNodeByNumber(iAnimationNumber);
2640  // slot 0 is reserved for ActMap animations
2641  if (!node || node->GetSlot() == 0 || node->GetType() != StdMeshInstance::AnimationNode::LeafNode)
2642  {
2643  return false;
2644  }
2645  StdMeshInstance::ValueProvider* p_provider = CreateValueProviderFromArray(Obj, *PositionProvider);
2646  if (!p_provider)
2647  {
2648  return false;
2649  }
2650  Instance->SetAnimationPosition(node, p_provider);
2651  return true;
2652 }
2653 
2654 static bool FnSetAnimationBoneTransform(C4Object *Obj, Nillable<int> iAnimationNumber, C4ValueArray* Transformation, Nillable<int> iAttachNumber)
2655 {
2656  if (!Obj)
2657  {
2658  return false;
2659  }
2660  if (!Obj->pMeshInstance)
2661  {
2662  return false;
2663  }
2664  if (iAnimationNumber.IsNil())
2665  {
2666  return false; // distinguish nil from 0
2667  }
2668 
2669  StdMeshInstance* Instance = Obj->pMeshInstance;
2670  if (!iAttachNumber.IsNil())
2671  {
2672  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2673  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2674  if (!Attached || !Attached->OwnChild)
2675  {
2676  return false;
2677  }
2678  Instance = Attached->Child;
2679  }
2680 
2681  StdMeshInstance::AnimationNode* node = Instance->GetAnimationNodeByNumber(iAnimationNumber);
2682  // slot 0 is reserved for ActMap animations
2683  if (!node || node->GetSlot() == 0 || node->GetType() != StdMeshInstance::AnimationNode::CustomNode)
2684  {
2685  return false;
2686  }
2687 
2688  StdMeshMatrix matrix;
2689  if (!C4ValueToMatrix(*Transformation, &matrix))
2690  {
2691  throw C4AulExecError("TransformBone: Transformation is not a valid 3x4 matrix");
2692  }
2693  // Here the same remark applies as in FnTransformBone
2694  StdMeshTransformation trans = matrix.Decompose();
2695 
2696  Instance->SetAnimationBoneTransform(node, trans);
2697  return true;
2698 }
2699 
2700 static bool FnSetAnimationWeight(C4Object *Obj, Nillable<int> iAnimationNumber, C4ValueArray* WeightProvider, Nillable<int> iAttachNumber)
2701 {
2702  if (!Obj)
2703  {
2704  return false;
2705  }
2706  if (!Obj->pMeshInstance)
2707  {
2708  return false;
2709  }
2710  if (iAnimationNumber.IsNil())
2711  {
2712  return false; // distinguish nil from 0
2713  }
2714 
2715  StdMeshInstance* Instance = Obj->pMeshInstance;
2716  if (!iAttachNumber.IsNil())
2717  {
2718  const StdMeshInstance::AttachedMesh* Attached = Instance->GetAttachedMeshByNumber(iAttachNumber);
2719  // OwnChild is set if an object's instance is attached. In that case the animation should be set directly on that object.
2720  if (!Attached || !Attached->OwnChild)
2721  {
2722  return false;
2723  }
2724  Instance = Attached->Child;
2725  }
2726 
2727  StdMeshInstance::AnimationNode* node = Instance->GetAnimationNodeByNumber(iAnimationNumber);
2728  // slot 0 is reserved for ActMap animations
2729  if (!node || node->GetSlot() == 0 || node->GetType() != StdMeshInstance::AnimationNode::LinearInterpolationNode)
2730  {
2731  return false;
2732  }
2733  StdMeshInstance::ValueProvider* w_provider = CreateValueProviderFromArray(Obj, *WeightProvider);
2734  if (!w_provider)
2735  {
2736  return false;
2737  }
2738  Instance->SetAnimationWeight(node, w_provider);
2739  return true;
2740 }
2741 
2742 static Nillable<int> FnAttachMesh(C4Object *Obj, C4PropList* Mesh, C4String * szParentBone, C4String * szChildBone, C4ValueArray * Transformation, int Flags, int AttachNumber)
2743 {
2744  if (!Obj->pMeshInstance)
2745  {
2746  return C4Void();
2747  }
2748  if (!Mesh)
2749  {
2750  return C4Void();
2751  }
2752 
2754  if (Transformation && !C4ValueToMatrix(*Transformation, &trans))
2755  {
2756  throw C4AulExecError("AttachMesh: Transformation is not a valid 3x4 matrix");
2757  }
2758 
2760  C4Object* pObj = Mesh->GetObject();
2761  if (pObj)
2762  {
2763  if (!pObj->pMeshInstance)
2764  {
2765  return C4Void();
2766  }
2767  attach = Obj->pMeshInstance->AttachMesh(*pObj->pMeshInstance, new C4MeshDenumerator(pObj), szParentBone->GetData(), szChildBone->GetData(), trans, Flags, false, AttachNumber);
2768  }
2769  else
2770  {
2771  C4Def* pDef = Mesh->GetDef();
2772  if (!pDef)
2773  {
2774  return C4Void();
2775  }
2776  if (pDef->Graphics.Type != C4DefGraphics::TYPE_Mesh)
2777  {
2778  return C4Void();
2779  }
2780  attach = Obj->pMeshInstance->AttachMesh(*pDef->Graphics.Mesh, new C4MeshDenumerator(pDef), szParentBone->GetData(), szChildBone->GetData(), trans, Flags, AttachNumber);
2781  if (attach)
2782  {
2784  }
2785  }
2786 
2787  if (!attach)
2788  {
2789  return C4Void();
2790  }
2791  return attach->Number;
2792 }
2793 
2794 static bool FnDetachMesh(C4Object *Obj, long iAttachNumber)
2795 {
2796  if (!Obj || !Obj->pMeshInstance)
2797  {
2798  return false;
2799  }
2800  return Obj->pMeshInstance->DetachMesh(iAttachNumber);
2801 }
2802 
2803 static bool FnSetAttachBones(C4Object *Obj, long iAttachNumber, Nillable<C4String*> szParentBone, Nillable<C4String*> szChildBone)
2804 {
2805  if (!Obj || !Obj->pMeshInstance)
2806  {
2807  return false;
2808  }
2810  if (!attach)
2811  {
2812  return false;
2813  }
2814 
2815  if (!szParentBone.IsNil())
2816  {
2817  C4String* ParentBone = szParentBone;
2818  if (!attach->SetParentBone(ParentBone->GetData()))
2819  {
2820  return false;
2821  }
2822  }
2823 
2824  if (!szChildBone.IsNil())
2825  {
2826  C4String* ChildBone = szChildBone;
2827  if (!attach->SetChildBone(ChildBone->GetData()))
2828  {
2829  return false;
2830  }
2831  }
2832 
2833  return true;
2834 }
2835 
2836 static bool FnSetAttachTransform(C4Object *Obj, long iAttachNumber, C4ValueArray* Transformation)
2837 {
2838  if (!Obj || !Obj->pMeshInstance)
2839  {
2840  return false;
2841  }
2842  if (!Transformation)
2843  {
2844  return false;
2845  }
2847  if (!attach)
2848  {
2849  return false;
2850  }
2851 
2852  StdMeshMatrix trans;
2853  if (!C4ValueToMatrix(*Transformation, &trans))
2854  {
2855  throw C4AulExecError("SetAttachTransform: Transformation is not a valid 3x4 matrix");
2856  }
2857 
2858  attach->SetAttachTransformation(trans);
2859  return true;
2860 }
2861 
2862 static Nillable<C4ValueArray*> FnGetBoneNames(C4PropList * _this) {
2863  C4Object *obj = Object(_this);
2864 
2865  auto fnMakeC4ValueArray = [](const size_t len, const std::function<C4Value(size_t i)> iterable) -> C4ValueArray* {
2866  auto retval = new C4ValueArray(len);
2867  for (size_t i = 0; i < len; ++i) {
2868  retval->SetItem(i, iterable(i));
2869  }
2870  return retval;
2871  };
2872 
2873  if (!obj)
2874  {
2875  if (!_this || !_this->GetDef())
2876  {
2877  throw NeedNonGlobalContext("GetBoneNames");
2878  }
2879  // Called in definition context -> Use definition default mesh
2880  C4Def *def = _this->GetDef();
2881  if (!def->Graphics.IsMesh())
2882  {
2883  return C4Void();
2884  }
2885  const StdMeshSkeleton & skeleton = def->Graphics.Mesh->GetSkeleton();
2886  const std::function<C4Value(size_t i)> fnGetBoneName = [&skeleton](size_t i = 0) { return C4VString(skeleton.GetBone(i).Name); };
2887  return fnMakeC4ValueArray(skeleton.GetNumBones(), fnGetBoneName);
2888  }
2889  else
2890  {
2891  // Called in object context: Use current object mesh
2892  if (!obj->pMeshInstance)
2893  {
2894  return C4Void();
2895  }
2896  const StdMeshSkeleton & skeleton = obj->pMeshInstance->GetMesh().GetSkeleton();
2897  const std::function<C4Value(size_t i)> fnGetBoneName = [&skeleton](size_t i = 0) { return C4VString(skeleton.GetBone(i).Name); };
2898  return fnMakeC4ValueArray(skeleton.GetNumBones(), fnGetBoneName);;
2899  }
2900 }
2901 
2902 static Nillable<C4String*> FnGetMeshMaterial(C4PropList * _this, int iSubMesh)
2903 {
2904  // Called in object or definition context?
2905  C4Object *Obj = Object(_this);
2906  if (!Obj)
2907  {
2908  if (!_this || !_this->GetDef())
2909  {
2910  throw NeedNonGlobalContext("GetMeshMaterial");
2911  }
2912  // Called in definition context: Get definition default mesh material
2913  C4Def *def = _this->GetDef();
2914  if (!def->Graphics.IsMesh())
2915  {
2916  return C4Void();
2917  }
2918  if (iSubMesh < 0 || (unsigned int)iSubMesh >= def->Graphics.Mesh->GetNumSubMeshes())
2919  {
2920  return C4Void();
2921  }
2922  const StdSubMesh &submesh = def->Graphics.Mesh->GetSubMesh(iSubMesh);
2923  return String(submesh.GetMaterial().Name.getData());
2924  }
2925  else
2926  {
2927  // Called in object context: Get material of mesh instance
2928  if (!Obj->pMeshInstance)
2929  {
2930  return C4Void();
2931  }
2932  if (iSubMesh < 0 || (unsigned int)iSubMesh >= Obj->pMeshInstance->GetNumSubMeshes())
2933  {
2934  return C4Void();
2935  }
2936  StdSubMeshInstance& submesh = Obj->pMeshInstance->GetSubMesh(iSubMesh);
2937  return String(submesh.GetMaterial().Name.getData());
2938  }
2939 }
2940 
2941 static bool FnSetMeshMaterial(C4Object *Obj, C4String* Material, int iSubMesh)
2942 {
2943  if (!Obj || !Obj->pMeshInstance)
2944  {
2945  return false;
2946  }
2947  if (iSubMesh < 0 || (unsigned int)iSubMesh >= Obj->pMeshInstance->GetNumSubMeshes())
2948  {
2949  return false;
2950  }
2951  if (!Material)
2952  {
2953  return false;
2954  }
2955 
2956  const StdMeshMaterial* material = ::MeshMaterialManager.GetMaterial(Material->GetData().getData());
2957  if (!material)
2958  {
2959  return false;
2960  }
2961 
2962  Obj->pMeshInstance->SetMaterial(iSubMesh, *material);
2963  return true;
2964 }
2965 
2966 
2967 static bool FnCreateParticleAtBone(C4Object* Obj, C4String* szName, C4String* szBoneName, C4ValueArray* Pos, C4ValueArray* Dir, C4Value lifetime, C4PropList *properties, int amount)
2968 {
2969  // safety
2970  if(!Obj || !Obj->Status)
2971  {
2972  return false;
2973  }
2974  // Get bone
2975  if(!Obj->pMeshInstance)
2976  {
2977  return false;
2978  }
2979  const StdMesh& mesh = Obj->pMeshInstance->GetMesh();
2980  const StdMeshBone* bone = mesh.GetSkeleton().GetBoneByName(szBoneName->GetData());
2981  if (!bone)
2982  {
2983  return false;
2984  }
2985  // get particle
2986  C4ParticleDef *pDef=::Particles.definitions.GetDef(FnStringPar(szName));
2987  if (!pDef)
2988  {
2989  return false;
2990  }
2991 #ifndef USE_CONSOLE
2992  // Get transform
2995  // Get offset and direction
2996  StdMeshVector x, dir;
2997  if (Pos)
2998  {
2999  if(Pos->GetSize() != 3)
3000  {
3001  throw C4AulExecError("CreateParticleAtBone: Pos is not a three-vector");
3002  }
3003  x.x = (*Pos).GetItem(0).getInt();
3004  x.y = (*Pos).GetItem(1).getInt();
3005  x.z = (*Pos).GetItem(2).getInt();
3006  }
3007  else
3008  {
3009  x.x = x.y = x.z = 0.0f;
3010  }
3011 
3012  if(Dir)
3013  {
3014  if(Dir->GetSize() != 3)
3015  {
3016  throw C4AulExecError("CreateParticleAtBone: Dir is not a three-vector");
3017  }
3018  dir.x = (*Dir).GetItem(0).getInt() / 10.0f;
3019  dir.y = (*Dir).GetItem(1).getInt() / 10.0f;
3020  dir.z = (*Dir).GetItem(2).getInt() / 10.0f;
3021  }
3022  else
3023  {
3024  dir.x = dir.y = dir.z = 0.0f;
3025  }
3026  // Apply the bone transformation to them, to go from bone coordinates
3027  // to mesh coordinates.
3028  // This is a good example why we should have different types for
3029  // position vectors and displacement vectors. TODO.
3030  StdMeshVector transformed_x = transform * x;
3031  transformed_x.x += transform(0,3);
3032  transformed_x.y += transform(1,3);
3033  transformed_x.z += transform(2,3);
3034  x = transformed_x;
3035  dir = transform * dir;
3036  // Apply MeshTransformation in the mesh reference frame
3037  C4Value value;
3038  Obj->GetProperty(P_MeshTransformation, &value);
3039  StdMeshMatrix MeshTransform;
3040  if (!C4ValueToMatrix(value, &MeshTransform))
3041  {
3042  MeshTransform = StdMeshMatrix::Identity();
3043  }
3044  x = MeshTransform * x;
3045  dir = MeshTransform * dir;
3046  x.x += MeshTransform(0,3);
3047  x.y += MeshTransform(1,3);
3048  x.z += MeshTransform(2,3);
3049  // Now go to world coordinates -- this code is copied from and needs to
3050  // stay in sync with C4DrawGL::PerformMesh, so the particles are
3051  // created at the correct position.
3052  // TODO: This should be moved into a common function.
3053  const StdMeshBox& box = mesh.GetBoundingBox();
3054  StdMeshVector v1;
3055  v1.x = box.x1;
3056  v1.y = box.y1;
3057  v1.z = box.z1;
3058  StdMeshVector v2;
3059  v2.x = box.x2;
3060  v2.y = box.y2;
3061  v2.z = box.z2;
3062  const float tx = fixtof(Obj->fix_x) + Obj->Def->Shape.GetX();
3063  const float ty = fixtof(Obj->fix_y) + Obj->Def->Shape.GetY();
3064  const float twdt = Obj->Def->Shape.Wdt;
3065  const float thgt = Obj->Def->Shape.Hgt;
3066  const float rx = -std::min(v1.x,v2.x) / fabs(v2.x - v1.x);
3067  const float ry = -std::min(v1.y,v2.y) / fabs(v2.y - v1.y);
3068  const float dx = tx + rx*twdt;
3069  const float dy = ty + ry*thgt;
3070  x.x += dx;
3071  x.y += dy;
3072  // This was added in the block before and could also just be removed from tx/ty.
3073  // However, the block would no longer be equal to where it came from.
3074  x.x -= fixtof(Obj->fix_x);
3075  x.y -= fixtof(Obj->fix_y);
3076  // Finally, apply DrawTransform to the world coordinates,
3077  // and incorporate object rotation into the transformation
3078  C4DrawTransform draw_transform;
3079  if (Obj->pDrawTransform)
3080  {
3081  draw_transform.SetTransformAt(*Obj->pDrawTransform, fixtof(Obj->fix_x), fixtof(Obj->fix_y));
3082  draw_transform.Rotate(fixtof(Obj->fix_r), 0.0f, 0.0f);
3083  }
3084  else
3085  {
3086  draw_transform.SetRotate(fixtof(Obj->fix_r), 0.0f, 0.0f);
3087  }
3088 
3089  StdMeshMatrix DrawTransform;
3090  DrawTransform(0, 0) = draw_transform.mat[0];
3091  DrawTransform(0, 1) = draw_transform.mat[1];
3092  DrawTransform(0, 2) = 0.0f;
3093  DrawTransform(0, 3) = draw_transform.mat[2];
3094  DrawTransform(1, 0) = draw_transform.mat[3];
3095  DrawTransform(1, 1) = draw_transform.mat[4];
3096  DrawTransform(1, 2) = 0.0f;
3097  DrawTransform(1, 3) = draw_transform.mat[5];
3098  DrawTransform(2, 0) = 0.0f;
3099  DrawTransform(2, 1) = 0.0f;
3100  DrawTransform(2, 2) = 1.0f;
3101  DrawTransform(2, 3) = 0.0f;
3102 
3103  x = DrawTransform * x;
3104  dir = DrawTransform * dir;
3105  x.x += DrawTransform(0,3);
3106  x.y += DrawTransform(1,3);
3107  x.z += DrawTransform(2,3);
3108 
3109  // construct data
3110  C4ParticleValueProvider valueX, valueY, valueSpeedX, valueSpeedY, valueLifetime;
3111  valueX.Set(x.x);
3112  valueY.Set(x.y);
3113  valueSpeedX.Set(dir.x);
3114  valueSpeedY.Set(dir.y);
3115  valueLifetime.Set(lifetime);
3116 
3117  // cast
3118  if (amount < 1)
3119  {
3120  amount = 1;
3121  }
3122  ::Particles.Create(pDef, valueX, valueY, valueSpeedX, valueSpeedY, valueLifetime, properties, amount, Obj);
3123 #endif
3124  // success, even if not created
3125  return true;
3126 
3127 }
3128 
3129 static Nillable<long> FnGetDefWidth(C4PropList * _this)
3130 {
3131  if (!_this)
3132  {
3133  return C4Void();
3134  }
3135  C4Def *def = _this->GetDef();
3136  if (!def)
3137  {
3138  return C4Void();
3139  }
3140  return def->Shape.Wdt;
3141 }
3142 
3143 static Nillable<long> FnGetDefHeight(C4PropList * _this)
3144 {
3145  if (!_this)
3146  {
3147  return C4Void();
3148  }
3149  C4Def *def = _this->GetDef();
3150  if (!def)
3151  {
3152  return C4Void();
3153  }
3154  return def->Shape.Hgt;
3155 }
3156 
3157 //=========================== C4Script Function Map ===================================
3158 
3160 {
3161  { "C4D_None" ,C4V_Int, C4D_None},
3162  { "C4D_All" ,C4V_Int, C4D_All},
3163  { "C4D_StaticBack" ,C4V_Int, C4D_StaticBack},
3164  { "C4D_Structure" ,C4V_Int, C4D_Structure},
3165  { "C4D_Vehicle" ,C4V_Int, C4D_Vehicle},
3166  { "C4D_Living" ,C4V_Int, C4D_Living},
3167  { "C4D_Object" ,C4V_Int, C4D_Object},
3168  { "C4D_Goal" ,C4V_Int, C4D_Goal},
3169  { "C4D_Environment" ,C4V_Int, C4D_Environment},
3170  { "C4D_Rule" ,C4V_Int, C4D_Rule},
3171  { "C4D_Background" ,C4V_Int, C4D_Background},
3172  { "C4D_Parallax" ,C4V_Int, C4D_Parallax},
3173  { "C4D_MouseSelect" ,C4V_Int, C4D_MouseSelect},
3174  { "C4D_Foreground" ,C4V_Int, C4D_Foreground},
3175  { "C4D_MouseIgnore" ,C4V_Int, C4D_MouseIgnore},
3176  { "C4D_IgnoreFoW" ,C4V_Int, C4D_IgnoreFoW},
3177 
3178  { "C4D_GrabGet" ,C4V_Int, C4D_Grab_Get},
3179  { "C4D_GrabPut" ,C4V_Int, C4D_Grab_Put},
3180 
3181  { "C4D_Border_Sides" ,C4V_Int, C4D_Border_Sides},
3182  { "C4D_Border_Top" ,C4V_Int, C4D_Border_Top},
3183  { "C4D_Border_Bottom" ,C4V_Int, C4D_Border_Bottom},
3184  { "C4D_Border_Layer" ,C4V_Int, C4D_Border_Layer},
3185 
3186  { "COMD_None" ,C4V_Int, COMD_None},
3187  { "COMD_Stop" ,C4V_Int, COMD_Stop},
3188  { "COMD_Up" ,C4V_Int, COMD_Up},
3189  { "COMD_UpRight" ,C4V_Int, COMD_UpRight},
3190  { "COMD_Right" ,C4V_Int, COMD_Right},
3191  { "COMD_DownRight" ,C4V_Int, COMD_DownRight},
3192  { "COMD_Down" ,C4V_Int, COMD_Down},
3193  { "COMD_DownLeft" ,C4V_Int, COMD_DownLeft},
3194  { "COMD_Left" ,C4V_Int, COMD_Left},
3195  { "COMD_UpLeft" ,C4V_Int, COMD_UpLeft},
3196 
3197  { "DIR_Left" ,C4V_Int, DIR_Left},
3198  { "DIR_Right" ,C4V_Int, DIR_Right},
3199 
3200  { "OCF_Construct" ,C4V_Int, OCF_Construct},
3201  { "OCF_Grab" ,C4V_Int, OCF_Grab},
3202  { "OCF_Collectible" ,C4V_Int, OCF_Carryable},
3203  { "OCF_OnFire" ,C4V_Int, OCF_OnFire},
3204  { "OCF_HitSpeed1" ,C4V_Int, OCF_HitSpeed1},
3205  { "OCF_Fullcon" ,C4V_Int, OCF_FullCon},
3206  { "OCF_Inflammable" ,C4V_Int, OCF_Inflammable},
3207  { "OCF_Rotate" ,C4V_Int, OCF_Rotate},
3208  { "OCF_Exclusive" ,C4V_Int, OCF_Exclusive},
3209  { "OCF_Entrance" ,C4V_Int, OCF_Entrance},
3210  { "OCF_HitSpeed2" ,C4V_Int, OCF_HitSpeed2},
3211  { "OCF_HitSpeed3" ,C4V_Int, OCF_HitSpeed3},
3212  { "OCF_Collection" ,C4V_Int, OCF_Collection},
3213  { "OCF_HitSpeed4" ,C4V_Int, OCF_HitSpeed4},
3214  { "OCF_NotContained" ,C4V_Int, OCF_NotContained},
3215  { "OCF_CrewMember" ,C4V_Int, OCF_CrewMember},
3216  { "OCF_InLiquid" ,C4V_Int, OCF_InLiquid},
3217  { "OCF_InSolid" ,C4V_Int, OCF_InSolid},
3218  { "OCF_InFree" ,C4V_Int, OCF_InFree},
3219  { "OCF_Available" ,C4V_Int, OCF_Available},
3220  { "OCF_Container" ,C4V_Int, OCF_Container},
3221  { "OCF_Alive" ,C4V_Int, (int) OCF_Alive},
3222 
3223  { "VIS_All" ,C4V_Int, VIS_All},
3224  { "VIS_None" ,C4V_Int, VIS_None},
3225  { "VIS_Owner" ,C4V_Int, VIS_Owner},
3226  { "VIS_Allies" ,C4V_Int, VIS_Allies},
3227  { "VIS_Enemies" ,C4V_Int, VIS_Enemies},
3228  { "VIS_Select" ,C4V_Int, VIS_Select},
3229  { "VIS_God" ,C4V_Int, VIS_God},
3230  { "VIS_LayerToggle" ,C4V_Int, VIS_LayerToggle},
3231  { "VIS_OverlayOnly" ,C4V_Int, VIS_OverlayOnly},
3232  { "VIS_Editor" ,C4V_Int, VIS_Editor},
3233 
3234  { "C4MN_Style_Normal" ,C4V_Int, C4MN_Style_Normal},
3235  { "C4MN_Style_Context" ,C4V_Int, C4MN_Style_Context},
3236  { "C4MN_Style_Info" ,C4V_Int, C4MN_Style_Info},
3237  { "C4MN_Style_Dialog" ,C4V_Int, C4MN_Style_Dialog},
3238  { "C4MN_Style_EqualItemHeight",C4V_Int, C4MN_Style_EqualItemHeight},
3239 
3240  { "C4MN_Extra_None" ,C4V_Int, C4MN_Extra_None},
3241  { "C4MN_Extra_Value" ,C4V_Int, C4MN_Extra_Value},
3242  { "C4MN_Extra_Info" ,C4V_Int, C4MN_Extra_Info},
3243 
3244  { "C4MN_Add_ImgRank" ,C4V_Int, C4MN_Add_ImgRank},
3245  { "C4MN_Add_ImgIndexed" ,C4V_Int, C4MN_Add_ImgIndexed},
3246  { "C4MN_Add_ImgObjRank" ,C4V_Int, C4MN_Add_ImgObjRank},
3247  { "C4MN_Add_ImgObject" ,C4V_Int, C4MN_Add_ImgObject},
3248  { "C4MN_Add_ImgTextSpec" ,C4V_Int, C4MN_Add_ImgTextSpec},
3249  { "C4MN_Add_ImgPropListSpec",C4V_Int, C4MN_Add_ImgPropListSpec},
3250  { "C4MN_Add_ImgColor" ,C4V_Int, C4MN_Add_ImgColor},
3251  { "C4MN_Add_PassValue" ,C4V_Int, C4MN_Add_PassValue},
3252  { "C4MN_Add_ForceCount" ,C4V_Int, C4MN_Add_ForceCount},
3253  { "C4MN_Add_ForceNoDesc" ,C4V_Int, C4MN_Add_ForceNoDesc},
3254 
3255  { "GFXOV_MODE_None" ,C4V_Int, C4GraphicsOverlay::MODE_None }, // gfx overlay modes
3256  { "GFXOV_MODE_Base" ,C4V_Int, C4GraphicsOverlay::MODE_Base }, //
3257  { "GFXOV_MODE_Action" ,C4V_Int, C4GraphicsOverlay::MODE_Action }, //
3258  { "GFXOV_MODE_Picture" ,C4V_Int, C4GraphicsOverlay::MODE_Picture }, //
3259  { "GFXOV_MODE_IngamePicture" ,C4V_Int, C4GraphicsOverlay::MODE_IngamePicture }, //
3260  { "GFXOV_MODE_Object" ,C4V_Int, C4GraphicsOverlay::MODE_Object }, //
3261  { "GFXOV_MODE_ExtraGraphics" ,C4V_Int, C4GraphicsOverlay::MODE_ExtraGraphics }, //
3262  { "GFXOV_MODE_Rank" ,C4V_Int, C4GraphicsOverlay::MODE_Rank}, //
3263  { "GFXOV_MODE_ObjectPicture" ,C4V_Int, C4GraphicsOverlay::MODE_ObjectPicture}, //
3264  { "GFX_Overlay" ,C4V_Int, 1}, // default overlay index
3265  { "GFXOV_Clothing" ,C4V_Int, 1000}, // overlay indices for clothes on Clonks, etc.
3266  { "GFXOV_Tools" ,C4V_Int, 2000}, // overlay indices for tools, weapons, etc.
3267  { "GFXOV_ProcessTarget" ,C4V_Int, 3000}, // overlay indices for objects processed by a Clonk
3268  { "GFXOV_Misc" ,C4V_Int, 5000}, // overlay indices for other stuff
3269  { "GFXOV_UI" ,C4V_Int, 6000}, // overlay indices for user interface
3270  { "GFX_BLIT_Additive" ,C4V_Int, C4GFXBLIT_ADDITIVE}, // blit modes
3271  { "GFX_BLIT_Mod2" ,C4V_Int, C4GFXBLIT_MOD2}, //
3272  { "GFX_BLIT_ClrSfc_OwnClr" ,C4V_Int, C4GFXBLIT_CLRSFC_OWNCLR}, //
3273  { "GFX_BLIT_ClrSfc_Mod2" ,C4V_Int, C4GFXBLIT_CLRSFC_MOD2}, //
3274  { "GFX_BLIT_Wireframe" ,C4V_Int, C4GFXBLIT_WIREFRAME}, //
3275  { "GFX_BLIT_Custom" ,C4V_Int, C4GFXBLIT_CUSTOM}, //
3276  { "GFX_BLIT_Parent" ,C4V_Int, C4GFXBLIT_PARENT}, //
3277 
3278  // contact attachment
3279  { "CNAT_None" ,C4V_Int, CNAT_None },
3280  { "CNAT_Left" ,C4V_Int, CNAT_Left },
3281  { "CNAT_Right" ,C4V_Int, CNAT_Right },
3282  { "CNAT_Top" ,C4V_Int, CNAT_Top },
3283  { "CNAT_Bottom" ,C4V_Int, CNAT_Bottom },
3284  { "CNAT_Center" ,C4V_Int, CNAT_Center },
3285  { "CNAT_MultiAttach" ,C4V_Int, CNAT_MultiAttach },
3286  { "CNAT_NoCollision" ,C4V_Int, CNAT_NoCollision },
3287  { "CNAT_PhaseHalfVehicle" ,C4V_Int, CNAT_PhaseHalfVehicle },
3288 
3289  // vertex data
3290  { "VTX_X" ,C4V_Int, VTX_X },
3291  { "VTX_Y" ,C4V_Int, VTX_Y },
3292  { "VTX_CNAT" ,C4V_Int, VTX_CNAT },
3293  { "VTX_Friction" ,C4V_Int, VTX_Friction },
3294 
3295  // vertex set mode
3296  { "VTX_SetPermanent" ,C4V_Int, VTX_SetPermanent },
3297  { "VTX_SetPermanentUpd" ,C4V_Int, VTX_SetPermanentUpd },
3298 
3299  { "C4OS_DELETED" ,C4V_Int, C4OS_DELETED },
3300  { "C4OS_NORMAL" ,C4V_Int, C4OS_NORMAL },
3301  { "C4OS_INACTIVE" ,C4V_Int, C4OS_INACTIVE },
3302 
3303  { "C4CMD_Base" ,C4V_Int, C4CMD_Mode_Base },
3304  { "C4CMD_SilentBase" ,C4V_Int, C4CMD_Mode_SilentBase },
3305  { "C4CMD_Sub" ,C4V_Int, C4CMD_Mode_Sub },
3306  { "C4CMD_SilentSub" ,C4V_Int, C4CMD_Mode_SilentSub },
3307 
3308  { "C4CMD_MoveTo_NoPosAdjust" ,C4V_Int, C4CMD_MoveTo_NoPosAdjust },
3309  { "C4CMD_MoveTo_PushTarget" ,C4V_Int, C4CMD_MoveTo_PushTarget },
3310  { "C4CMD_Enter_PushTarget" ,C4V_Int, C4CMD_Enter_PushTarget },
3311 
3312  { "C4AVP_Const" ,C4V_Int, C4AVP_Const },
3313  { "C4AVP_Linear" ,C4V_Int, C4AVP_Linear },
3314  { "C4AVP_X" ,C4V_Int, C4AVP_X },
3315  { "C4AVP_Y" ,C4V_Int, C4AVP_Y },
3316  { "C4AVP_R" ,C4V_Int, C4AVP_R },
3317  { "C4AVP_AbsX" ,C4V_Int, C4AVP_AbsX },
3318  { "C4AVP_AbsY" ,C4V_Int, C4AVP_AbsY },
3319  { "C4AVP_Dist" ,C4V_Int, C4AVP_Dist },
3320  { "C4AVP_XDir" ,C4V_Int, C4AVP_XDir },
3321  { "C4AVP_YDir" ,C4V_Int, C4AVP_YDir },
3322  { "C4AVP_RDir" ,C4V_Int, C4AVP_RDir },
3323  { "C4AVP_AbsRDir" ,C4V_Int, C4AVP_AbsRDir },
3324  { "C4AVP_CosR" ,C4V_Int, C4AVP_CosR },
3325  { "C4AVP_SinR" ,C4V_Int, C4AVP_SinR },
3326  { "C4AVP_CosV" ,C4V_Int, C4AVP_CosV },
3327  { "C4AVP_SinV" ,C4V_Int, C4AVP_SinV },
3328  { "C4AVP_Action" ,C4V_Int, C4AVP_Action },
3329 
3330  { "ANIM_Loop" ,C4V_Int, ANIM_Loop },
3331  { "ANIM_Hold" ,C4V_Int, ANIM_Hold },
3332  { "ANIM_Remove" ,C4V_Int, ANIM_Remove },
3333 
3334  { "AM_None" ,C4V_Int, StdMeshInstance::AM_None },
3335  { "AM_DrawBefore" ,C4V_Int, StdMeshInstance::AM_DrawBefore },
3336  { "AM_MatchSkeleton" ,C4V_Int, StdMeshInstance::AM_MatchSkeleton },
3337 
3338  { nullptr, C4V_Nil, 0}
3339 };
3340 
3341 
3343 {
3344  // add all def constants (all Int)
3345  for (C4ScriptConstDef *pCDef = &C4ScriptObjectConstMap[0]; pCDef->Identifier; pCDef++)
3346  {
3347  assert(pCDef->ValType == C4V_Int); // only int supported currently
3348  pEngine->RegisterGlobalConstant(pCDef->Identifier, C4VInt(pCDef->Data));
3349  }
3350  C4PropListStatic * p = pEngine->GetPropList();
3351 #define F(f) ::AddFunc(p, #f, Fn##f)
3352 
3353  F(DoCon);
3354  F(GetCon);
3355  F(DoDamage);
3356  F(DoEnergy);
3357  F(DoBreath);
3358  F(GetEnergy);
3359  F(OnFire);
3360  F(Stuck);
3361  F(InLiquid);
3362  F(SetAction);
3363  F(SetActionData);
3364 
3365  F(GetAction);
3366  F(GetActTime);
3367  F(GetOwner);
3368  F(GetMass);
3369  F(GetBreath);
3370  F(GetMenu);
3371  F(GetVertexNum);
3372  F(GetVertex);
3373  F(SetVertex);
3374  F(AddVertex);
3375  F(InsertVertex);
3376  F(RemoveVertex);
3377  ::AddFunc(p, "SetContactDensity", FnSetContactDensity, false);
3378  F(GetController);
3379  F(SetController);
3380  F(SetName);
3381  F(GetKiller);
3382  F(SetKiller);
3383  F(GetPhase);
3384  F(SetPhase);
3385  F(GetCategory);
3386  F(GetOCF);
3387  F(SetAlive);
3388  F(GetAlive);
3389  F(GetDamage);
3390  F(SetComDir);
3391  F(GetComDir);
3392  F(SetDir);
3393  F(GetDir);
3394  F(SetEntrance);
3395  F(GetEntrance);
3396  F(SetCategory);
3397  F(FinishCommand);
3398  F(ActIdle);
3399  F(SetRDir);
3400  F(GetRDir);
3401  F(GetXDir);
3402  F(GetYDir);
3403  F(GetR);
3404  F(SetXDir);
3405  F(SetYDir);
3406  F(SetR);
3407  F(SetOwner);
3408  F(MakeCrewMember);
3409  F(GrabObjectInfo);
3410  F(CreateContents);
3411  F(ShiftContents);
3412  F(GetID);
3413  F(Contents);
3414  F(ScrollContents);
3415  F(Contained);
3416  F(ContentsCount);
3417  ::AddFunc(p, "FindContents", FnFindContents, false);
3418  ::AddFunc(p, "FindOtherContents", FnFindOtherContents, false);
3419  F(RemoveObject);
3420  F(GetActionTarget);
3421  F(SetActionTargets);
3422  ::AddFunc(p, "SetCrewStatus", FnSetCrewStatus, false);
3423  F(SetPosition);
3424  F(CreateMenu);
3425  F(AddMenuItem);
3426  F(SelectMenuItem);
3427  F(SetMenuDecoration);
3428  F(SetMenuTextProgress);
3429  F(ObjectDistance);
3430  F(GetValue);
3431  F(GetRank);
3432  F(SetTransferZone);
3433  F(SetMass);
3434  F(GetColor);
3435  F(SetColor);
3436  F(SetLightRange);
3437  F(GetLightColor);
3438  F(SetLightColor);
3439  F(SetPicture);
3440  F(GetProcedure);
3441  F(CanConcatPictureWith);
3442  F(SetGraphics);
3443  F(ObjectNumber);
3444  F(ShowInfo);
3445  F(CheckVisibility);
3446  F(SetClrModulation);
3448  F(CloseMenu);
3449  F(GetMenuSelection);
3450  F(GetDefBottom);
3451  F(SetMenuSize);
3452  F(GetCrewEnabled);
3453  F(SetCrewEnabled);
3454  F(DoCrewExp);
3455  F(ClearMenuItems);
3456  F(GetObjectLayer);
3457  F(SetObjectLayer);
3458  F(SetShape);
3459  F(SetObjDrawTransform);
3460  ::AddFunc(p, "SetObjDrawTransform2", FnSetObjDrawTransform2, false);
3461  ::AddFunc(p, "SetObjectStatus", FnSetObjectStatus, false);
3462  ::AddFunc(p, "GetObjectStatus", FnGetObjectStatus, false);
3463  ::AddFunc(p, "AdjustWalkRotation", FnAdjustWalkRotation, false);
3464  F(GetContact);
3465  F(SetObjectBlitMode);
3466  F(GetObjectBlitMode);
3467  ::AddFunc(p, "GetUnusedOverlayID", FnGetUnusedOverlayID, false);
3468  F(ExecuteCommand);
3469 
3470  F(PlayAnimation);
3471  F(TransformBone);
3472  F(StopAnimation);
3473  F(GetRootAnimation);
3474  F(GetAnimationList);
3475  F(GetAnimationLength);
3476  F(GetAnimationName);
3477  F(GetAnimationPosition);
3478  F(GetAnimationWeight);
3479  F(SetAnimationPosition);
3480  F(SetAnimationBoneTransform);
3481  F(SetAnimationWeight);
3482  F(AttachMesh);
3483  F(DetachMesh);
3484  F(SetAttachBones);
3485  F(SetAttachTransform);
3486  F(GetBoneNames);
3487  F(GetMeshMaterial);
3488  F(SetMeshMaterial);
3489  F(CreateParticleAtBone);
3490  F(ChangeDef);
3491  F(GrabContents);
3492  F(Punch);
3493  F(Kill);
3494  F(Fling);
3495  ::AddFunc(p, "Jump", FnJump, false);
3496  F(Enter);
3497  F(DeathAnnounce);
3498  F(SetSolidMask);
3499  F(SetHalfVehicleSolidMask);
3500  F(Exit);
3501  F(Collect);
3502 
3503  F(SetCommand);
3504  F(AddCommand);
3505  F(AppendCommand);
3506  F(GetCommand);
3507  F(SetCrewExtraData);
3508  F(GetCrewExtraData);
3509  F(GetDefWidth);
3510  F(GetDefHeight);
3511 #undef F
3512 }
C4Object * Object(C4PropList *_this)
Definition: C4AulDefFunc.h:34
C4String * String(const char *str)
Definition: C4AulDefFunc.h:30
void AddFunc(C4PropListStatic *Parent, const char *Name, RType(*pFunc)(ThisType *, ParTypes...), bool Public=true)
Definition: C4AulDefFunc.h:261
const char * Identifier
Definition: C4AulDefFunc.h:269
int32_t CommandByName(const char *szCommand)
Definition: C4Command.cpp:126
const char * CommandName(int32_t iCommand)
Definition: C4Command.cpp:46
const int32_t C4CMD_MoveTo_NoPosAdjust
Definition: C4Command.h:65
const int32_t C4CMD_Mode_SilentBase
Definition: C4Command.h:61
@ C4CMD_Call
Definition: C4Command.h:51
const int32_t C4CMD_MoveTo_PushTarget
Definition: C4Command.h:66
const int32_t C4CMD_Mode_Base
Definition: C4Command.h:60
const int32_t C4CMD_Enter_PushTarget
Definition: C4Command.h:68
const int32_t C4CMD_Mode_Sub
Definition: C4Command.h:62
const int32_t C4CMD_Mode_SilentSub
Definition: C4Command.h:59
#define s
bool AddMenuItem(C4ConsoleGUI *console, HMENU hMenu, DWORD dwID, const char *szString, bool fEnabled)
const uint32_t OCF_Carryable
Definition: C4Constants.h:82
const int32_t FullCon
Definition: C4Constants.h:181
const uint32_t OCF_Inflammable
Definition: C4Constants.h:86
const uint32_t OCF_Grab
Definition: C4Constants.h:81
const uint32_t OCF_Construct
Definition: C4Constants.h:80
const uint32_t OCF_InFree
Definition: C4Constants.h:100
const BYTE CNAT_Bottom
Definition: C4Constants.h:112
const uint32_t OCF_HitSpeed1
Definition: C4Constants.h:84
const int32_t MNone
Definition: C4Constants.h:177
const size_t C4MaxTitle
Definition: C4Constants.h:25
const uint32_t OCF_Collection
Definition: C4Constants.h:93
const int C4SymbolSize
Definition: C4Constants.h:58
const uint32_t OCF_HitSpeed4
Definition: C4Constants.h:95
const uint32_t OCF_OnFire
Definition: C4Constants.h:83
const uint32_t OCF_Entrance
Definition: C4Constants.h:90
const uint32_t OCF_Alive
Definition: C4Constants.h:103
const uint32_t OCF_Container
Definition: C4Constants.h:102
const uint32_t OCF_Available
Definition: C4Constants.h:101
const uint32_t OCF_Exclusive
Definition: C4Constants.h:89
const uint32_t OCF_Rotate
Definition: C4Constants.h:88
const uint32_t OCF_HitSpeed3
Definition: C4Constants.h:92
const BYTE CNAT_Center
Definition: C4Constants.h:113
const BYTE CNAT_Right
Definition: C4Constants.h:110
const BYTE CNAT_Top
Definition: C4Constants.h:111
const BYTE CNAT_NoCollision
Definition: C4Constants.h:116
const BYTE CNAT_PhaseHalfVehicle
Definition: C4Constants.h:117
const uint32_t OCF_InSolid
Definition: C4Constants.h:99
const uint32_t OCF_FullCon
Definition: C4Constants.h:85
const uint32_t OCF_NotContained
Definition: C4Constants.h:96
const BYTE CNAT_MultiAttach
Definition: C4Constants.h:115
const uint32_t OCF_HitSpeed2
Definition: C4Constants.h:91
const uint32_t OCF_CrewMember
Definition: C4Constants.h:97
const uint32_t OCF_InLiquid
Definition: C4Constants.h:98
const BYTE CNAT_None
Definition: C4Constants.h:108
const int C4D_MaxVertex
Definition: C4Constants.h:55
const int NO_OWNER
Definition: C4Constants.h:137
const BYTE CNAT_Left
Definition: C4Constants.h:109
const int32_t C4D_Goal
Definition: C4Def.h:46
const int32_t C4D_Foreground
Definition: C4Def.h:53
const int32_t C4D_IgnoreFoW
Definition: C4Def.h:55
const int32_t C4D_MouseSelect
Definition: C4Def.h:52
const int32_t C4D_Rule
Definition: C4Def.h:47
const int32_t C4D_All
Definition: C4Def.h:39
const int32_t C4D_Border_Bottom
Definition: C4Def.h:67
const int32_t C4D_Background
Definition: C4Def.h:50
const int32_t C4D_Structure
Definition: C4Def.h:41
const int32_t C4D_Living
Definition: C4Def.h:43
const int32_t C4D_MouseIgnore
Definition: C4Def.h:54
const int32_t C4D_Grab_Put
Definition: C4Def.h:62
const int32_t C4D_StaticBack
Definition: C4Def.h:40
const int32_t C4D_Border_Layer
Definition: C4Def.h:68
const int32_t C4D_Grab_Get
Definition: C4Def.h:63
const int32_t C4D_Object
Definition: C4Def.h:44
const int32_t C4D_None
Definition: C4Def.h:38
const int32_t C4D_Border_Top
Definition: C4Def.h:66
const int32_t C4D_Environment
Definition: C4Def.h:48
const int32_t C4D_Parallax
Definition: C4Def.h:51
const int32_t C4D_Vehicle
Definition: C4Def.h:42
const int32_t C4D_Border_Sides
Definition: C4Def.h:65
C4Def * C4Id2Def(C4ID id)
Definition: C4DefList.h:84
#define C4FxCall_EngScript
Definition: C4Effect.h:55
#define C4FxCall_DmgScript
Definition: C4Effect.h:49
#define C4Fx_AnyFire
Definition: C4Effect.h:149
void GameMsgObject(const char *szText, C4Object *pTarget)
#define PSF_CrewEnabled
Definition: C4GameScript.h:148
#define PSF_CrewDisabled
Definition: C4GameScript.h:149
#define PSF_NameChange
Definition: C4GameScript.h:150
C4Game Game
Definition: C4Globals.cpp:52
C4GraphicsResource GraphicsResource
int iResult
Definition: C4GroupMain.cpp:40
const int32_t C4MaxPhysical
Definition: C4InfoCore.h:28
const unsigned int C4MaxName
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
bool Log(const char *szMessage)
Definition: C4Log.cpp:204
bool DebugLog(const char *strMessage)
Definition: C4Log.cpp:282
bool DebugLogF(const char *strMessage ...)
Definition: C4Log.cpp:290
@ C4MN_Extra_Info
Definition: C4Menu.h:46
@ C4MN_Extra_Value
Definition: C4Menu.h:45
@ C4MN_Extra_None
Definition: C4Menu.h:44
@ C4MN_Item_NoCount
Definition: C4Menu.h:58
@ C4MN_Style_Dialog
Definition: C4Menu.h:38
@ C4MN_Style_Normal
Definition: C4Menu.h:35
@ C4MN_Style_Context
Definition: C4Menu.h:36
@ C4MN_Style_Info
Definition: C4Menu.h:37
@ C4MN_Style_EqualItemHeight
Definition: C4Menu.h:40
@ C4MN_SymbolSize
Definition: C4Menu.h:30
StdMeshInstance::ValueProvider * CreateValueProviderFromArray(C4Object *pForObj, C4ValueArray &Data, const StdMeshAnimation *pos_for_animation)
@ C4AVP_XDir
@ C4AVP_CosV
@ C4AVP_YDir
@ C4AVP_X
@ C4AVP_Y
@ C4AVP_AbsY
@ C4AVP_Dist
@ C4AVP_Linear
@ C4AVP_AbsRDir
@ C4AVP_AbsX
@ C4AVP_Action
@ C4AVP_R
@ C4AVP_CosR
@ C4AVP_SinR
@ C4AVP_Const
@ C4AVP_SinV
@ C4AVP_RDir
@ ANIM_Remove
@ ANIM_Hold
@ ANIM_Loop
#define VIS_God
Definition: C4Object.h:68
#define VIS_None
Definition: C4Object.h:63
#define VIS_All
Definition: C4Object.h:62
#define COMD_UpLeft
Definition: C4Object.h:58
#define COMD_DownRight
Definition: C4Object.h:54
#define COMD_Down
Definition: C4Object.h:55
#define DIR_Right
Definition: C4Object.h:42
#define COMD_DownLeft
Definition: C4Object.h:56
#define DIR_Left
Definition: C4Object.h:41
#define VIS_Owner
Definition: C4Object.h:64
#define VIS_Select
Definition: C4Object.h:67
#define C4OS_INACTIVE
Definition: C4Object.h:36
#define C4OS_NORMAL
Definition: C4Object.h:35
#define VIS_Enemies
Definition: C4Object.h:66
#define VIS_OverlayOnly
Definition: C4Object.h:70
#define COMD_UpRight
Definition: C4Object.h:52
#define VIS_LayerToggle
Definition: C4Object.h:69
#define COMD_Right
Definition: C4Object.h:53
#define VIS_Editor
Definition: C4Object.h:71
#define VIS_Allies
Definition: C4Object.h:65
#define COMD_Left
Definition: C4Object.h:57
#define COMD_Stop
Definition: C4Object.h:50
#define COMD_Up
Definition: C4Object.h:51
#define C4OS_DELETED
Definition: C4Object.h:34
#define COMD_None
Definition: C4Object.h:49
bool ObjectComPunch(C4Object *cObj, C4Object *pTarget, int32_t punch)
bool ObjectComCancelAttach(C4Object *cObj)
bool ObjectComJump(C4Object *cObj)
@ C4MN_Info
Definition: C4ObjectMenu.h:41
const int C4MN_Add_ImgRank
const int C4MN_Add_ForceNoDesc
#define L2F(l)
const int C4MN_Add_ImgIndexed
const int C4MN_Add_ImgTextSpec
const int C4MN_Add_ImgColor
const int C4MN_Add_ImgPropListSpec
const int C4MN_Add_PassValue
#define F(f)
const int C4MN_Add_ImgObjRank
VertexUpdateMode
@ VTX_SetNonpermanent
@ VTX_SetPermanent
@ VTX_SetPermanentUpd
const int C4MN_Add_MaxImage
VertexDataIndex
@ VTX_X
@ VTX_CNAT
@ VTX_Friction
@ VTX_Y
bool C4ValueToMatrix(C4Value &value, StdMeshMatrix *matrix)
const int C4MN_Add_ForceCount
C4ScriptConstDef C4ScriptObjectConstMap[]
void InitObjectFunctionMap(C4AulScriptEngine *pEngine)
const int C4MN_Add_ImgObject
C4ParticleSystem Particles
const int32_t C4PVM_Cursor
Definition: C4Player.h:31
const int32_t C4PVM_Target
Definition: C4Player.h:32
C4PlayerList Players
int32_t ValidPlr(int32_t plr)
uint32_t UnsyncedRandom()
Definition: C4Random.cpp:58
float fixtof(const C4Fixed &x)
Definition: C4Real.h:257
C4Fixed itofix(int32_t x)
Definition: C4Real.h:261
int fixtoi(const C4Fixed &x)
Definition: C4Real.h:259
C4Fixed ftofix(float x)
Definition: C4Real.h:258
const C4Real Fix1
Definition: C4Real.h:313
#define C4D_VertexCpyPos
Definition: C4Rect.h:23
@ DFA_ATTACH
@ P_MeshTransformation
@ P_Procedure
#define C4GFXBLIT_PARENT
Definition: C4Surface.h:36
#define C4GFXBLIT_WIREFRAME
Definition: C4Surface.h:30
#define C4GFXBLIT_CLRSFC_OWNCLR
Definition: C4Surface.h:28
#define C4GFXBLIT_ADDITIVE
Definition: C4Surface.h:26
#define C4GFXBLIT_MOD2
Definition: C4Surface.h:27
#define C4GFXBLIT_CUSTOM
Definition: C4Surface.h:35
#define C4GFXBLIT_CLRSFC_MOD2
Definition: C4Surface.h:29
const char * GetC4VName(const C4V_Type Type)
Definition: C4Value.cpp:32
C4Value C4VObj(C4Object *pObj)
Definition: C4Value.cpp:88
const C4Value C4VNull
Definition: C4Value.cpp:30
@ C4V_Int
Definition: C4Value.h:26
@ C4V_PropList
Definition: C4Value.h:28
@ C4V_Object
Definition: C4Value.h:38
@ C4V_Bool
Definition: C4Value.h:27
@ C4V_Array
Definition: C4Value.h:30
@ C4V_Nil
Definition: C4Value.h:25
@ C4V_String
Definition: C4Value.h:29
C4Value C4VInt(int32_t i)
Definition: C4Value.h:239
C4Value C4VString(C4String *pStr)
Definition: C4Value.h:243
uint32_t DWORD
const char * SSearch(const char *szString, const char *szIndex)
Definition: Standard.cpp:369
bool IsIdentifier(char cChar)
Definition: Standard.cpp:90
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:152
int32_t Distance(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2)
Definition: Standard.cpp:25
void SAppendChar(char cChar, char *szStr)
Definition: Standard.cpp:271
#define sprintf
Definition: Standard.h:162
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
size_t SLen(const char *sptr)
Definition: Standard.h:74
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
DWORD GetClrModulation(DWORD dwSrcClr, DWORD dwDstClr, DWORD &dwBack)
Definition: StdColors.h:112
StdMeshMatManager MeshMaterialManager
int32_t Data
Definition: C4Object.h:84
int32_t t_attach
Definition: C4Object.h:86
int32_t Time
Definition: C4Object.h:83
int32_t Phase
Definition: C4Object.h:85
C4ObjectPtr Target2
Definition: C4Object.h:87
int32_t ComDir
Definition: C4Object.h:82
int32_t Dir
Definition: C4Object.h:80
C4ObjectPtr Target
Definition: C4Object.h:87
C4PropListStatic * GetPropList()
Definition: C4Aul.h:151
void RegisterGlobalConstant(const char *szName, const C4Value &rValue)
Definition: C4Aul.cpp:123
void SetRotate(float iAngle, float fOffX, float fOffY)
void Rotate(float Angle, float fOffX, float fOffY)
void Set(float fA, float fB, float fC, float fD, float fE, float fF, float fG, float fH, float fI)
int32_t Failures
Definition: C4Command.h:88
int32_t Finished
Definition: C4Command.h:87
C4Value Tx
Definition: C4Command.h:82
C4ObjectPtr Target
Definition: C4Command.h:84
C4ObjectPtr Target2
Definition: C4Command.h:84
int32_t Ty
Definition: C4Command.h:83
int32_t Command
Definition: C4Command.h:81
C4String * Text
Definition: C4Command.h:89
C4Command * Next
Definition: C4Command.h:90
C4DefGraphics * Get(const char *szGrpName)
GraphicsType Type
Definition: C4DefGraphics.h:48
bool IsMesh() const
Definition: C4DefGraphics.h:73
Definition: C4Def.h:99
int32_t Mass
Definition: C4Def.h:114
C4DefGraphics Graphics
Definition: C4Def.h:191
int32_t iNumRankSymbols
Definition: C4Def.h:190
C4FacetSurface * pRankSymbols
Definition: C4Def.h:189
C4ID id
Definition: C4Def.h:101
int32_t Rotateable
Definition: C4Def.h:119
int32_t Category
Definition: C4Def.h:117
C4Shape Shape
Definition: C4Def.h:104
void Draw(C4Facet &cgo, bool fSelected=false, DWORD iColor=0, C4Object *pObj=nullptr, int32_t iPhaseX=0, int32_t iPhaseY=0, C4DrawTransform *trans=nullptr, const char *graphicsName=nullptr)
Definition: C4Def.cpp:607
int32_t BlitMode
Definition: C4Def.h:141
int32_t GetValue(C4Object *pInBase, int32_t iBuyPlayer)
Definition: C4Def.cpp:621
void Set(float fA, float fB, float fC, float fD, float fE, float fF, float fG, float fH, float fI)
Definition: C4Facet.h:76
void SetTransformAt(C4DrawTransform &rCopy, float iOffX, float iOffY)
Definition: C4Facet.cpp:541
int32_t FlipDir
Definition: C4Facet.h:50
C4Effect * Get(const char *szName, int32_t iIndex=0, int32_t iMaxPriority=0)
Definition: C4Effect.cpp:210
float Hgt
Definition: C4Facet.h:118
float Wdt
Definition: C4Facet.h:118
float X
Definition: C4Facet.h:118
bool Create(int iWdt, int iHgt, int iWdt2=C4FCT_Full, int iHgt2=C4FCT_Full)
Definition: C4FacetEx.cpp:54
void Set(const C4Facet &cpy)
Definition: C4FacetEx.h:46
Definition: C4Real.h:59
void SetFrameDeco(FrameDecoration *pNewDeco)
Definition: C4Gui.h:2194
bool SetByDef(C4Def *pSrcDef)
C4Scenario C4S
Definition: C4Game.h:74
C4TransferZones TransferZones
Definition: C4Game.h:85
bool DrawPropListSpecImage(C4Facet &target, C4PropList *spec)
Definition: C4Game.cpp:4692
bool DrawTextSpecImage(C4Facet &target, const char *spec, class C4DrawTransform *transform, uint32_t color=0xff)
Definition: C4Game.cpp:4626
uint32_t GetClrModulation() const
bool IsValid(const C4Object *pForObj) const
void SetAsObject(C4Object *pOverlayObj, DWORD dwBMode)
void SetBlitMode(uint32_t dwToMode)
void SetAsExtraGraphics(C4DefGraphics *pGfx, DWORD dwBMode)
void SetAsPicture(C4DefGraphics *pBaseGfx, DWORD dwBMode)
uint32_t GetBlitMode() const
void SetAsRank(DWORD dwBMode, C4Object *rank_obj)
void SetAsIngamePicture(C4DefGraphics *pBaseGfx, DWORD dwBMode)
C4DrawTransform * GetTransform()
void SetAsAction(C4DefGraphics *pBaseGfx, const char *szAction, DWORD dwBMode)
void SetAsObjectPicture(C4Object *pOverlayObj, DWORD dwBMode)
void SetClrModulation(uint32_t dwToMod)
void SetAsBase(C4DefGraphics *pBaseGfx, DWORD dwBMode)
Definition: C4Id.h:26
const char * ToString() const
Definition: C4Id.h:56
static const C4ID None
Definition: C4Id.h:39
Definition: C4Menu.h:123
bool Add(const char *szCaption, C4FacetSurface &fctSymbol, const char *szCommand, int32_t iCount=C4MN_Item_NoCount, C4Object *pObject=nullptr, const char *szInfoCaption=nullptr, C4ID idID=C4ID::None, const char *szCommand2=nullptr, bool fOwnValue=false, int32_t iValue=0, bool fIsSelectable=true)
Definition: C4Menu.cpp:350
int GetSymbolSize()
Definition: C4Menu.h:165
void SetPermanent(bool fPermanent)
Definition: C4Menu.cpp:862
bool SetTextProgress(int32_t iToProgress, bool fAdd)
Definition: C4Menu.cpp:958
int32_t GetItemHeight()
Definition: C4Menu.h:166
int32_t GetIdentification()
Definition: C4Menu.cpp:612
void ClearItems()
Definition: C4Menu.cpp:895
int32_t GetSelection()
Definition: C4Menu.cpp:599
bool SetSelection(int32_t iSelection, bool fAdjustPosition, bool fDoCalls)
Definition: C4Menu.cpp:544
bool IsActive()
Definition: C4Menu.cpp:480
bool IsContextMenu()
Definition: C4Menu.h:164
void SetSize(int32_t iToWdt, int32_t iToHgt)
Definition: C4Menu.cpp:617
int32_t OwnMass
Definition: C4Object.h:113
bool Enter(C4Object *pTarget, bool fCalls=true, bool fCopyMotion=true, bool *pfRejectCollect=nullptr)
bool EntranceStatus
Definition: C4Object.h:130
C4ObjectInfo * Info
Definition: C4Object.h:143
bool SetGraphics(const char *szGraphicsName=nullptr, C4Def *pSourceDef=nullptr)
C4Real ydir
Definition: C4Object.h:124
C4Real fix_y
Definition: C4Object.h:123
bool ShiftContents(bool fShiftBack, bool fDoCalls)
void SetHalfVehicleSolidMask(bool set)
C4PropList * GetAction() const
void UpdatLastEnergyLossCause(int32_t iNewCausePlr)
Definition: C4Object.cpp:611
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)
void UpdateMass()
C4Real xdir
Definition: C4Object.h:124
void DoExperience(int32_t change)
void UpdateFace(bool bUpdateShape, bool fTemp=false)
C4Rect PictureRect
Definition: C4Object.h:150
bool GrabInfo(C4Object *pFrom)
Definition: C4Object.cpp:1153
int32_t GetValue(C4Object *pInBase, int32_t iForPlayer)
Definition: C4Object.cpp:791
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)
void ClearCommands()
bool AdjustWalkRotation(int32_t iRangeX, int32_t iRangeY, int32_t iSpeed)
C4Real fix_x
Definition: C4Object.h:123
bool SetActionByName(C4String *ActName, C4Object *pTarget=nullptr, C4Object *pTarget2=nullptr, int32_t iCalls=SAC_StartCall|SAC_AbortCall, bool fForce=false)
C4Effect * pEffects
Definition: C4Object.h:155
int32_t GetProcedure() const
C4Object * CreateContents(C4PropList *)
C4DrawTransform * pDrawTransform
Definition: C4Object.h:135
C4Command * Command
Definition: C4Object.h:165
bool StatusActivate()
Definition: C4Object.cpp:1202
int32_t Owner
Definition: C4Object.h:108
bool CrewDisabled
Definition: C4Object.h:162
void SetName(const char *NewName=nullptr) override
Definition: C4Object.cpp:783
int32_t GetX() const
Definition: C4Object.h:285
int32_t Category
Definition: C4Object.h:111
bool ActivateMenu(int32_t iMenu, int32_t iMenuSelect=0, int32_t iMenuData=0, int32_t iMenuPosition=0, C4Object *pTarget=nullptr)
void SetAlive(bool Alive)
Definition: C4Object.h:303
bool IsVisible(int32_t iForPlr, bool fAsOverlay) const
class C4ObjectMenu * Menu
Definition: C4Object.h:138
void SetCategory(int32_t Category)
Definition: C4Object.h:256
int32_t Controller
Definition: C4Object.h:109
void UpdateInLiquid()
void SetDir(int32_t tdir)
uint32_t OCF
Definition: C4Object.h:132
bool GetAlive() const
Definition: C4Object.h:304
void Fling(C4Real txdir, C4Real tydir, bool fAddSpeed)
C4Real fix_r
Definition: C4Object.h:123
void ForcePosition(C4Real target_x, C4Real target_y)
Definition: C4Movement.cpp:667
bool GetOnFire() const
Definition: C4Object.h:302
bool Mobile
Definition: C4Object.h:126
bool SetLightRange(int32_t iToRange, int32_t iToFadeoutRange)
bool ExecuteCommand()
void DirectComContents(C4Object *pTarget, bool fDoCalls)
int32_t Damage
Definition: C4Object.h:114
bool SetLightColor(uint32_t iValue)
bool CloseMenu(bool fForce)
int32_t Breath
Definition: C4Object.h:116
bool RemoveGraphicsOverlay(int32_t iOverlayID)
C4ObjectPtr Layer
Definition: C4Object.h:134
bool fOwnVertices
Definition: C4Object.h:147
int32_t GetY() const
Definition: C4Object.h:286
StdMeshInstance * pMeshInstance
Definition: C4Object.h:154
void AssignDeath(bool fForced)
Definition: C4Object.cpp:467
void DoCon(int32_t iChange, bool grow_from_center)
Definition: C4Object.cpp:631
void BoundsCheck(C4Real &target_x, C4Real &target_y)
Definition: C4Object.h:330
int32_t LastEnergyLossCausePlayer
Definition: C4Object.h:110
void AssignRemoval(bool exit_contents=false)
Definition: C4Object.cpp:215
bool Collect(C4Object *pObj)
C4NotifyingObjectList Contents
Definition: C4Object.h:151
int32_t GetR() const
Definition: C4Object.h:287
int32_t GetCon() const
Definition: C4Object.h:271
C4ObjectPtr Contained
Definition: C4Object.h:142
C4Real rdir
Definition: C4Object.h:124
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)
bool StatusDeactivate(bool fClearPointers)
Definition: C4Object.cpp:1218
C4Action Action
Definition: C4Object.h:145
int32_t Energy
Definition: C4Object.h:115
int32_t Mass
Definition: C4Object.h:113
bool InLiquid
Definition: C4Object.h:129
void GrabContents(C4Object *pFrom)
bool ChangeDef(C4ID idNew)
Definition: C4Object.cpp:518
uint32_t BlitMode
Definition: C4Object.h:161
uint32_t GetLightColor() const
Definition: C4Object.h:299
uint32_t ColorMod
Definition: C4Object.h:160
void DoDamage(int32_t iLevel, int32_t iCausedByPlr, int32_t iCause)
Definition: C4Object.cpp:571
@ SAC_StartCall
Definition: C4Object.h:250
@ SAC_AbortCall
Definition: C4Object.h:250
bool CanConcatPictureWith(C4Object *pOtherObject) const
C4Def * Def
Definition: C4Object.h:141
void UpdatePos()
uint32_t Color
Definition: C4Object.h:118
void SetSolidMask(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY)
void UpdateShape(bool bUpdateVertices=true)
Definition: C4Object.cpp:327
bool SetPhase(int32_t iPhase)
void SetRotation(int32_t nr)
bool SetOwner(int32_t iOwner)
Definition: C4Object.cpp:1129
C4Shape Shape
Definition: C4Object.h:146
class C4GraphicsOverlay * GetGraphicsOverlay(int32_t iForID) const
void UpdateGraphics(bool fGraphicsChanged, bool fTemp=false)
void DoBreath(int32_t iChange)
Definition: C4Object.cpp:622
void DoEnergy(int32_t iChange, bool fExact, int32_t iCause, int32_t iCausedByPlr)
Definition: C4Object.cpp:585
char Name[C4MaxName+1]
Definition: C4InfoCore.h:37
char DeathMessage[C4MaxDeathMsg+1]
Definition: C4InfoCore.h:48
C4ValueMapData ExtraData
Definition: C4InfoCore.h:49
void MakeValidName(char *sName)
bool NameExists(const char *szName)
virtual bool Add(C4Object *new_obj, SortType sort_type, C4ObjectList *sorted_list=nullptr)
C4Object * Find(C4Def *def, int owner=ANY_OWNER, DWORD dwOCF=OCF_All)
virtual bool Remove(C4Object *obj)
int ObjectCount(C4ID id=C4ID::None) const
C4Object * FindOther(C4ID id, int owner=ANY_OWNER)
C4Object * GetObject(int index=0) const
bool Init(C4FacetSurface &fctSymbol, const char *szEmpty, C4Object *pObject, int32_t iExtra=C4MN_Extra_None, int32_t iExtraData=0, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal, bool fUserMenu=false)
C4ParticleDef * GetDef(const char *name, C4ParticleDef *exclude=nullptr)
C4ParticleSystemDefinitionList definitions
Definition: C4Particles.h:510
void Create(C4ParticleDef *of_def, C4ParticleValueProvider &x, C4ParticleValueProvider &y, C4ParticleValueProvider &speedX, C4ParticleValueProvider &speedY, C4ParticleValueProvider &lifetime, C4PropList *properties, int amount=1, C4Object *object=nullptr)
void Set(const C4Value &value)
C4ObjectPtr Cursor
Definition: C4Player.h:130
C4ObjectInfoList CrewInfoList
Definition: C4Player.h:124
int32_t ViewMode
Definition: C4Player.h:105
C4ObjectPtr ViewCursor
Definition: C4Player.h:130
void AdjustCursorCommand()
Definition: C4Player.cpp:1059
void SetViewMode(int32_t iMode, C4Object *pTarget=nullptr, bool immediate_position=false)
Definition: C4Player.cpp:767
bool MakeCrewMember(C4Object *pObj, bool fForceInfo=true, bool fDoCalls=true)
Definition: C4Player.cpp:1008
bool SetObjectCrewStatus(C4Object *pCrew, bool fNewStatus)
Definition: C4Player.cpp:1557
C4Player * Get(int iPlayer) const
virtual void SetName(const char *NewName=nullptr)
Definition: C4PropList.cpp:625
virtual C4Object * GetObject()
Definition: C4PropList.cpp:636
virtual const char * GetName() const
Definition: C4PropList.cpp:618
int32_t Status
Definition: C4PropList.h:173
C4PropertyName GetPropertyP(C4PropertyName k) const
Definition: C4PropList.cpp:824
C4PropList * GetPrototype() const
Definition: C4PropList.h:85
C4String * GetPropertyStr(C4PropertyName k) const
Definition: C4PropList.cpp:744
virtual C4Def const * GetDef() const
Definition: C4PropList.cpp:654
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4PropList.h:114
bool GetProperty(C4PropertyName k, C4Value *pResult) const
Definition: C4PropList.h:105
const char * GetName() const override
Definition: C4PropList.cpp:243
static bool DrawRankSymbol(C4FacetSurface *fctSymbol, int32_t iRank, C4Facet *pfctRankSymbols, int32_t iRankSymbolCount, bool fOwnSurface, int32_t iXOff=0, C4Facet *cgoDrawDirect=nullptr)
int32_t y
Definition: C4Rect.h:30
int32_t Hgt
Definition: C4Rect.h:30
int32_t Wdt
Definition: C4Rect.h:30
int32_t x
Definition: C4Rect.h:30
void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt)
Definition: C4Rect.cpp:86
int32_t Film
Definition: C4Scenario.h:73
C4SHead Head
Definition: C4Scenario.h:232
bool AddVertex(int32_t iX, int32_t iY)
Definition: C4Shape.cpp:28
int32_t AttachMat
Definition: C4Shape.h:50
bool InsertVertex(int32_t iPos, int32_t tx, int32_t ty)
Definition: C4Shape.cpp:376
int GetBottom()
Definition: C4Shape.cpp:575
int32_t GetX() const
Definition: C4Shape.h:62
bool CheckContact(int32_t cx, int32_t cy)
Definition: C4Shape.cpp:413
void CreateOwnOriginalCopy(C4Shape &rFrom)
Definition: C4Shape.cpp:637
int32_t VtxCNAT[C4D_MaxVertex]
Definition: C4Shape.h:45
int32_t ContactDensity
Definition: C4Shape.h:47
int32_t VtxNum
Definition: C4Shape.h:42
int32_t VtxFriction[C4D_MaxVertex]
Definition: C4Shape.h:46
int32_t GetY() const
Definition: C4Shape.h:63
bool RemoveVertex(int32_t iPos)
Definition: C4Shape.cpp:398
int32_t GetVertexContact(int32_t iVtx, DWORD dwCheckMask, int32_t tx, int32_t ty, const C4DensityProvider &rDensityProvider=DefaultDensityProvider)
Definition: C4Shape.cpp:603
int32_t VtxY[C4D_MaxVertex]
Definition: C4Shape.h:44
int32_t VtxX[C4D_MaxVertex]
Definition: C4Shape.h:43
StdStrBuf GetData() const
Definition: C4StringTable.h:50
const char * GetCStr() const
Definition: C4StringTable.h:49
bool Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, C4Object *pObj)
void SetItem(int32_t iElemNr, const C4Value &Value)
int32_t GetSize() const
Definition: C4ValueArray.h:36
C4ValueArray * getArray() const
Definition: C4Value.h:118
ALWAYS_INLINE bool CheckConversion(C4V_Type vtToType) const
Definition: C4Value.h:189
C4Object * getObj() const
Definition: C4Value.cpp:68
int32_t getInt() const
Definition: C4Value.h:112
C4String * getStr() const
Definition: C4Value.h:117
C4V_Type GetType() const
Definition: C4Value.h:161
bool getBool() const
Definition: C4Value.h:113
C4PropList * getPropList() const
Definition: C4Value.h:116
const char * GetTypeName() const
Definition: C4Value.h:164
C4ValueMapNames * pNames
Definition: C4ValueMap.h:44
C4ValueMapNames * CreateTempNameList()
Definition: C4ValueMap.cpp:146
int32_t AddName(const char *pnName)
Definition: C4ValueMap.cpp:429
int32_t GetItemNr(const char *strName) const
Definition: C4ValueMap.cpp:459
bool IsNil() const
Definition: C4AulDefFunc.h:58
StdCopyStrBuf Name
Definition: StdMesh.h:97
float Length
Definition: StdMesh.h:98
StdMeshTransformation Transformation
Definition: StdMesh.h:37
unsigned int Index
Definition: StdMesh.h:32
StdCopyStrBuf Name
Definition: StdMesh.h:34
const StdMeshBox & GetBoundingBox() const
Definition: StdMesh.h:206
const StdMeshSkeleton & GetSkeleton() const
Definition: StdMesh.h:203
bool SetChildBone(const StdStrBuf &bone)
Definition: StdMesh.cpp:1001
void SetAttachTransformation(const StdMeshMatrix &transformation)
Definition: StdMesh.cpp:1011
StdMeshInstance * Child
Definition: StdMesh.h:511
bool SetParentBone(const StdStrBuf &bone)
Definition: StdMesh.cpp:991
C4Real GetWeight() const
Definition: StdMesh.h:357
C4Real GetPosition() const
Definition: StdMesh.h:352
NodeType GetType() const
Definition: StdMesh.h:347
unsigned int GetNumber() const
Definition: StdMesh.h:346
const StdMeshAnimation * GetAnimation() const
Definition: StdMesh.h:350
void SetMaterial(size_t i, const StdMeshMaterial &material)
Definition: StdMesh.cpp:1437
bool DetachMesh(unsigned int number)
Definition: StdMesh.cpp:1395
AnimationNode * GetRootAnimationForSlot(int slot)
Definition: StdMesh.cpp:1253
bool UpdateBoneTransforms()
Definition: StdMesh.cpp:1471
AnimationNode * PlayAnimation(const StdStrBuf &animation_name, int slot, AnimationNode *sibling, ValueProvider *position, ValueProvider *weight, bool stop_previous_animation)
Definition: StdMesh.cpp:1167
void SetFaceOrderingForClrModulation(uint32_t clrmod)
Definition: StdMesh.cpp:1135
void StopAnimation(AnimationNode *node)
Definition: StdMesh.cpp:1190
AttachedMesh * GetAttachedMeshByNumber(unsigned int number) const
Definition: StdMesh.cpp:1419
const StdMesh & GetMesh() const
Definition: StdMesh.h:622
void SetAnimationPosition(AnimationNode *node, ValueProvider *position)
Definition: StdMesh.cpp:1260
AnimationNode * GetAnimationNodeByNumber(unsigned int number)
Definition: StdMesh.cpp:1247
StdSubMeshInstance & GetSubMesh(size_t i)
Definition: StdMesh.h:589
void SetAnimationBoneTransform(AnimationNode *node, const StdMeshTransformation &trans)
Definition: StdMesh.cpp:1271
AttachedMesh * AttachMesh(const StdMesh &mesh, AttachedMesh::Denumerator *denumerator, const StdStrBuf &parent_bone, const StdStrBuf &child_bone, const StdMeshMatrix &transformation=StdMeshMatrix::Identity(), uint32_t flags=AM_None, unsigned int attach_number=0)
Definition: StdMesh.cpp:1333
size_t GetNumSubMeshes() const
Definition: StdMesh.h:588
const StdMeshMatrix & GetBoneTransform(size_t i) const
Definition: StdMesh.cpp:1446
void SetAnimationWeight(AnimationNode *node, ValueProvider *weight)
Definition: StdMesh.cpp:1278
const StdMeshMaterial * GetMaterial(const char *material_name) const
StdCopyStrBuf Name
static StdMeshMatrix Identity()
StdMeshTransformation Decompose() const
static StdMeshMatrix Transform(const StdMeshTransformation &transform)
const StdMeshBone * GetBoneByName(const StdStrBuf &name) const
Definition: StdMesh.cpp:388
std::vector< const StdMeshAnimation * > GetAnimations() const
Definition: StdMesh.cpp:406
const StdMeshBone & GetBone(size_t i) const
Definition: StdMesh.h:116
const StdMeshAnimation * GetAnimationByName(const StdStrBuf &name) const
Definition: StdMesh.cpp:398
size_t GetNumBones() const
Definition: StdMesh.h:117
const char * getData() const
Definition: StdBuf.h:442
const StdMeshMaterial & GetMaterial() const
Definition: StdMesh.h:170
const StdMeshMaterial & GetMaterial() const
Definition: StdMesh.h:270
float y2
Definition: StdMesh.h:147
float z1
Definition: StdMesh.h:146
float z2
Definition: StdMesh.h:147
float x2
Definition: StdMesh.h:147
float y1
Definition: StdMesh.h:146
float x1
Definition: StdMesh.h:146