OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4GameScript.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 /* Functions mapped by C4Script */
19 
20 #include "C4Include.h"
22 #include "game/C4GameScript.h"
23 
24 #include "control/C4GameControl.h"
25 #include "control/C4RoundResults.h"
26 #include "editor/C4Console.h"
27 #include "game/C4Application.h"
28 #include "game/C4GraphicsSystem.h"
29 #include "game/C4Viewport.h"
31 #include "graphics/C4Shader.h"
32 #include "gui/C4GameMessage.h"
33 #include "gui/C4MessageInput.h"
34 #include "gui/C4MouseControl.h"
35 #include "gui/C4ScriptGuiWindow.h"
36 #include "landscape/C4Landscape.h"
37 #include "landscape/C4PXS.h"
38 #include "landscape/C4Particles.h"
39 #include "landscape/C4Sky.h"
40 #include "landscape/C4Texture.h"
41 #include "landscape/C4Weather.h"
42 #include "landscape/fow/C4FoW.h"
43 #include "object/C4Command.h"
44 #include "object/C4DefList.h"
45 #include "object/C4GameObjects.h"
46 #include "platform/C4GamePadCon.h"
47 #include "player/C4Player.h"
48 #include "player/C4PlayerList.h"
49 #include "script/C4AulDefFunc.h"
50 
52 {
53  if (pTarget)
54  {
55  if (pTarget == ScriptEngine.GetPropList())
57  if (pTarget == GameScript.ScenPropList.getPropList())
59  C4Object * Obj = pTarget->GetObject();
60  if (!Obj)
61  throw C4AulExecError("Effect target has to be an object");
62  return &Obj->pEffects;
63  }
65 }
66 
67 // undocumented!
68 static bool FnIncinerateLandscape(C4PropList * _this, long iX, long iY, long caused_by_plr)
69 {
70  if (Object(_this)) { iX += Object(_this)->GetX(); iY += Object(_this)->GetY(); }
71  return !!::Landscape.Incinerate(iX, iY, caused_by_plr);
72 }
73 
74 static void FnSetGravity(C4PropList * _this, long iGravity)
75 {
76  ::Landscape.SetGravity(C4REAL100(Clamp<long>(iGravity,-1000,1000)));
77 }
78 
79 static long FnGetGravity(C4PropList * _this)
80 {
81  return fixtoi(::Landscape.GetGravity() * 100);
82 }
83 
84 static C4String *FnGetPlayerName(C4PropList * _this, long iPlayer)
85 {
86  if (!ValidPlr(iPlayer)) return nullptr;
87  return String(::Players.Get(iPlayer)->GetName());
88 }
89 
90 static long FnGetPlayerType(C4PropList * _this, long iPlayer)
91 {
92  C4Player *pPlr = ::Players.Get(iPlayer);
93  if (!pPlr) return 0;
94  return pPlr->GetType();
95 }
96 
97 static long FnGetPlayerColor(C4PropList * _this, long iPlayer)
98 {
99  C4Player *plr = ::Players.Get(iPlayer);
100  return plr ? plr->ColorDw : 0;
101 }
102 
103 // undocumented!
104 static Nillable<long> FnGetPlrClonkSkin(C4PropList * _this, long iPlayer)
105 {
106  C4Player *plr = ::Players.Get(iPlayer);
107  if (plr)
108  return plr->PrefClonkSkin;
109  return C4Void();
110 }
111 
112 static Nillable<long> FnGetX(C4PropList * _this, long iPrec)
113 {
114  if (!Object(_this)) return C4Void();
115  if (!iPrec) iPrec = 1;
116  return fixtoi(Object(_this)->fix_x, iPrec);
117 }
118 
119 static Nillable<long> FnGetY(C4PropList * _this, long iPrec)
120 {
121  if (!Object(_this)) return C4Void();
122  if (!iPrec) iPrec = 1;
123  return fixtoi(Object(_this)->fix_y, iPrec);
124 }
125 
126 static C4Object *FnCreateObjectAbove(C4PropList * _this,
127  C4PropList * PropList, long iXOffset, long iYOffset, Nillable<long> owner)
128 {
129  if (Object(_this)) // Local object calls override
130  {
131  iXOffset += Object(_this)->GetX();
132  iYOffset += Object(_this)->GetY();
133  }
134 
135  long iOwner = owner;
136  if (owner.IsNil())
137  {
138  if (Object(_this))
139  iOwner = Object(_this)->Controller;
140  else
141  iOwner = NO_OWNER;
142  }
143 
144  C4Object *pNewObj = Game.CreateObject(PropList, Object(_this), iOwner, iXOffset, iYOffset);
145 
146  // Set initial controller to creating controller, so more complicated cause-effect-chains can be traced back to the causing player
147  if (pNewObj && Object(_this) && Object(_this)->Controller > NO_OWNER) pNewObj->Controller = Object(_this)->Controller;
148 
149  return pNewObj;
150 }
151 
152 static C4Object *FnCreateObject(C4PropList * _this,
153  C4PropList * PropList, long iXOffset, long iYOffset, Nillable<long> owner)
154 {
155  if (Object(_this)) // Local object calls override
156  {
157  iXOffset += Object(_this)->GetX();
158  iYOffset += Object(_this)->GetY();
159  }
160 
161  long iOwner = owner;
162  if (owner.IsNil())
163  {
164  if (Object(_this))
165  iOwner = Object(_this)->Controller;
166  else
167  iOwner = NO_OWNER;
168  }
169 
170  C4Object *pNewObj = Game.CreateObject(PropList, Object(_this), iOwner, iXOffset, iYOffset, 0, true);
171 
172  // Set initial controller to creating controller, so more complicated cause-effect-chains can be traced back to the causing player
173  if (pNewObj && Object(_this) && Object(_this)->Controller > NO_OWNER) pNewObj->Controller = Object(_this)->Controller;
174 
175  return pNewObj;
176 }
177 
178 
179 static C4Object *FnCreateConstruction(C4PropList * _this,
180  C4PropList * PropList, long iXOffset, long iYOffset, Nillable<long> owner,
181  long iCompletion, bool fTerrain, bool fCheckSite)
182 {
183  // Make sure parameters are valid
184  if (!PropList || !PropList->GetDef())
185  return nullptr;
186 
187  // Local object calls override position offset, owner
188  if (Object(_this))
189  {
190  iXOffset+=Object(_this)->GetX();
191  iYOffset+=Object(_this)->GetY();
192  }
193 
194  // Check site
195  if (fCheckSite)
196  if (!ConstructionCheck(PropList,iXOffset,iYOffset,Object(_this)))
197  return nullptr;
198 
199  long iOwner = owner;
200  if (owner.IsNil())
201  {
202  if (Object(_this))
203  iOwner = Object(_this)->Controller;
204  else
205  iOwner = NO_OWNER;
206  }
207 
208  // Create site object
209  C4Object *pNewObj = Game.CreateObjectConstruction(PropList,Object(_this),iOwner,iXOffset,iYOffset,iCompletion*FullCon/100,fTerrain);
210 
211  // Set initial controller to creating controller, so more complicated cause-effect-chains can be traced back to the causing player
212  if (pNewObj && Object(_this) && Object(_this)->Controller>NO_OWNER) pNewObj->Controller = Object(_this)->Controller;
213 
214  return pNewObj;
215 }
216 
217 static C4ValueArray *FnFindConstructionSite(C4PropList * _this, C4PropList * PropList, int32_t v1, int32_t v2)
218 {
219  // Get def
220  C4Def *pDef;
221  if (!(pDef=PropList->GetDef())) return nullptr;
222  // Construction check at starting position
223  if (ConstructionCheck(PropList,v1,v2))
224  return nullptr;
225  // Search for real
226  bool result = !!FindConSiteSpot(v1, v2, pDef->Shape.Wdt,pDef->Shape.Hgt, 20);
227  if(!result) return nullptr;
228  auto *pArray = new C4ValueArray(2);
229  pArray->SetItem(0, C4VInt(v1));
230  pArray->SetItem(1, C4VInt(v2));
231  return pArray;
232 }
233 
234 static bool FnCheckConstructionSite(C4PropList * _this, C4PropList * PropList, int32_t iXOffset, int32_t iYOffset)
235 {
236  // Make sure parameters are valid
237  if (!PropList || !PropList->GetDef())
238  return false;
239 
240  // Local object calls override position offset, owner
241  if (Object(_this))
242  {
243  iXOffset+=Object(_this)->GetX();
244  iYOffset+=Object(_this)->GetY();
245  }
246 
247  // Check construction site
248  return ConstructionCheck(PropList, iXOffset, iYOffset);
249 }
250 
252 {
253  int i, iCnt = 0, iSortCnt = 0;
254  bool has_layer_check = false;
255  // Read all parameters
256  for (i = 0; i < C4AUL_MAX_Par; i++)
257  {
258  C4Value Data = *(pPars++);
259  // No data given?
260  if (!Data) break;
261  // Construct
262  C4SortObject *pSO = nullptr;
263  C4FindObject *pFO = C4FindObject::CreateByValue(Data, pSOs ? &pSO : nullptr, context, &has_layer_check);
264  // Add FindObject
265  if (pFO)
266  {
267  pFOs[iCnt++] = pFO;
268  }
269  // Add SortObject
270  if (pSO)
271  {
272  pSOs[iSortCnt++] = pSO;
273  }
274  }
275  // No criterions?
276  if (!iCnt)
277  {
278  for (i = 0; i < iSortCnt; ++i) delete pSOs[i];
279  return nullptr;
280  }
281  // Implicit layer check
282  if (context && !has_layer_check)
283  {
284  pFOs[iCnt++] = new C4FindObjectLayer(context->Layer);
285  }
286  // create sort criterion
287  C4SortObject *pSO = nullptr;
288  if (iSortCnt)
289  {
290  if (iSortCnt == 1)
291  pSO = pSOs[0];
292  else
293  pSO = new C4SortObjectMultiple(iSortCnt, pSOs, false);
294  }
295  // Create search object
296  C4FindObject *pFO;
297  if (iCnt == 1)
298  pFO = pFOs[0];
299  else
300  pFO = new C4FindObjectAnd(iCnt, pFOs, false);
301  if (pSO) pFO->SetSort(pSO);
302  return pFO;
303 }
304 
305 static C4Value FnObjectCount(C4PropList * _this, C4Value *pPars)
306 {
307  // Create FindObject-structure
308  C4FindObject *pFOs[C4AUL_MAX_Par+1]; // +1 array element to include space for implicit layer check
309  C4FindObject *pFO = CreateCriterionsFromPars(pPars, pFOs, nullptr, Object(_this));
310  // Error?
311  if (!pFO)
312  throw C4AulExecError("ObjectCount: No valid search criterions supplied");
313  // Search
314  int32_t iCnt = pFO->Count(::Objects, ::Objects.Sectors);
315  // Free
316  delete pFO;
317  // Return
318  return C4VInt(iCnt);
319 }
320 
321 static C4Value FnFindObject(C4PropList * _this, C4Value *pPars)
322 {
323  // Create FindObject-structure
324  C4FindObject *pFOs[C4AUL_MAX_Par]; // +1 array element to include space for implicit layer check
326  C4FindObject *pFO = CreateCriterionsFromPars(pPars, pFOs, pSOs, Object(_this));
327  // Error?
328  if (!pFO)
329  throw C4AulExecError("FindObject: No valid search criterions supplied");
330  // Search
331  C4Object *pObj = pFO->Find(::Objects, ::Objects.Sectors);
332  // Free
333  delete pFO;
334  // Return
335  return C4VObj(pObj);
336 }
337 
338 static C4Value FnFindObjects(C4PropList * _this, C4Value *pPars)
339 {
340  // Create FindObject-structure
341  C4FindObject *pFOs[C4AUL_MAX_Par]; // +1 array element to include space for implicit layer check
343  C4FindObject *pFO = CreateCriterionsFromPars(pPars, pFOs, pSOs, Object(_this));
344  // Error?
345  if (!pFO)
346  throw C4AulExecError("FindObjects: No valid search criterions supplied");
347  // Search
348  C4ValueArray *pResult = pFO->FindMany(::Objects, ::Objects.Sectors);
349  // Free
350  delete pFO;
351  // Return
352  return C4VArray(pResult);
353 }
354 
355 static bool FnInsertMaterial(C4PropList * _this, long mat, long x, long y, long vx, long vy, C4PropList *insert_position)
356 {
357  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
358  int32_t insert_x=x, insert_y=y;
359  if (!::Landscape.InsertMaterial(mat,&insert_x,&insert_y,vx,vy)) return false;
360  // output insertion position if desired (may be out of landscape range)
361  if (insert_position && !insert_position->IsFrozen())
362  {
363  insert_position->SetProperty(P_X, C4VInt(insert_x));
364  insert_position->SetProperty(P_Y, C4VInt(insert_y));
365  }
366  return true;
367 }
368 
369 static bool FnCanInsertMaterial(C4PropList * _this, long mat, long x, long y, C4PropList *insert_position)
370 {
371  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
372  int32_t insert_x=x, insert_y=y;
373  if (!::Landscape.InsertMaterial(mat,&insert_x,&insert_y,0,0,true)) return false;
374  // output insertion position if desired
375  if (insert_position && !insert_position->IsFrozen())
376  {
377  insert_position->SetProperty(P_X, C4VInt(insert_x));
378  insert_position->SetProperty(P_Y, C4VInt(insert_y));
379  }
380  return true;
381 }
382 
383 static long FnGetMaterialCount(C4PropList * _this, long iMaterial, bool fReal)
384 {
385  if (!MatValid(iMaterial)) return -1;
386  if (fReal || !::MaterialMap.Map[iMaterial].MinHeightCount)
387  return ::Landscape.GetMatCount(iMaterial);
388  else
390 }
391 
392 static long FnGetMaterial(C4PropList * _this, long x, long y)
393 {
394  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
395  return GBackMat(x,y);
396 }
397 
398 static long FnGetBackMaterial(C4PropList * _this, long x, long y)
399 {
400  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
402 }
403 
404 static C4String *FnGetTexture(C4PropList * _this, long x, long y)
405 {
406  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
407 
408  // Get texture
409  int32_t iTex = PixCol2Tex(::Landscape.GetPix(x, y));
410  if (!iTex) return nullptr;
411  // Get material-texture mapping
412  const C4TexMapEntry *pTex = ::TextureMap.GetEntry(iTex);
413  if (!pTex) return nullptr;
414  // Return tex name
415  return String(pTex->GetTextureName());
416 }
417 
418 static C4String *FnGetBackTexture(C4PropList * _this, long x, long y)
419 {
420  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
421 
422  // Get texture
423  int32_t iTex = PixCol2Tex(::Landscape.GetBackPix(x, y));
424  if (!iTex) return nullptr;
425  // Get material-texture mapping
426  const C4TexMapEntry *pTex = ::TextureMap.GetEntry(iTex);
427  if (!pTex) return nullptr;
428  // Return tex name
429  return String(pTex->GetTextureName());
430 }
431 
432 // Note: Might be async in case of 16<->32 bit textures!
433 static Nillable<long> FnGetAverageTextureColor(C4PropList * _this, C4String* Texture)
434 {
435  // Safety
436  if(!Texture) return C4Void();
437  // Check texture
438  StdStrBuf texture_name;
439  texture_name.Ref(Texture->GetCStr());
440  const char* pch = strchr(texture_name.getData(), '-');
441  if (pch != nullptr)
442  {
443  size_t len = pch - texture_name.getData();
444  texture_name.Copy();
445  texture_name.SetLength(len);
446  }
447  C4Texture* Tex = ::TextureMap.GetTexture(texture_name.getData());
448  if(!Tex) return C4Void();
449  return Tex->GetAverageColor();
450 }
451 
452 static bool FnGBackSolid(C4PropList * _this, long x, long y)
453 {
454  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
455  return GBackSolid(x,y);
456 }
457 
458 static bool FnGBackSemiSolid(C4PropList * _this, long x, long y)
459 {
460  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
461  return GBackSemiSolid(x,y);
462 }
463 
464 static bool FnGBackLiquid(C4PropList * _this, long x, long y)
465 {
466  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
467  return GBackLiquid(x,y);
468 }
469 
470 static bool FnGBackSky(C4PropList * _this, long x, long y)
471 {
472  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
473  return Landscape.GetBackPix(x, y) == 0;
474 }
475 
476 static long FnExtractMaterialAmount(C4PropList * _this, long x, long y, long mat, long amount, bool distant_first)
477 {
478  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
479  long extracted=0; for (; extracted<amount; extracted++)
480  {
481  if (GBackMat(x,y)!=mat) return extracted;
482  if (::Landscape.ExtractMaterial(x,y,distant_first)!=mat) return extracted;
483  }
484  return extracted;
485 }
486 
487 static void FnBlastFree(C4PropList * _this, long iX, long iY, long iLevel, Nillable<long> iCausedBy, Nillable<long> iMaxDensity)
488 {
489  if (iCausedBy.IsNil() && Object(_this)) iCausedBy = Object(_this)->Controller;
490  if (iMaxDensity.IsNil()) iMaxDensity = C4M_Vehicle;
491 
492  ::Landscape.BlastFree(iX, iY, iLevel, iCausedBy, Object(_this), iMaxDensity);
493 }
494 
495 static bool FnSoundAt(C4PropList * _this, C4String *szSound, long iX, long iY, Nillable<long> iLevel, Nillable<long> iAtPlayer, long iCustomFalloffDistance, long iPitch, C4PropList *modifier_props)
496 {
497  // play here?
498  if (!iAtPlayer.IsNil())
499  {
500  // get player to play at
501  C4Player *pPlr = ::Players.Get(iAtPlayer);
502  // not existant? fail
503  if (!pPlr) return false;
504  // network client: don't play here
505  // return true for network sync
506  if (!pPlr->LocalControl) return true;
507  }
508  // even less than nothing?
509  if (iLevel<0) return true;
510  // default sound level
511  if (iLevel.IsNil() || iLevel>100)
512  iLevel=100;
513  // modifier from prop list
514  C4SoundModifier *modifier;
515  if (modifier_props)
516  modifier = Application.SoundSystem.Modifiers.Get(modifier_props, true);
517  else
518  modifier = nullptr;
519  // target object
520  C4Object *pObj = Object(_this);
521  if (pObj)
522  {
523  iX += pObj->GetX();
524  iY += pObj->GetY();
525  }
526  StartSoundEffectAt(FnStringPar(szSound), iX, iY, iLevel, iCustomFalloffDistance, iPitch, modifier);
527  // always return true (network safety!)
528  return true;
529 }
530 
531 static bool FnSound(C4PropList * _this, C4String *szSound, bool fGlobal, Nillable<long> iLevel, Nillable<long> iAtPlayer, long iLoop, long iCustomFalloffDistance, long iPitch, C4PropList *modifier_props)
532 {
533  // play here?
534  if (!iAtPlayer.IsNil())
535  {
536  // get player to play at
537  C4Player *pPlr = ::Players.Get(iAtPlayer);
538  // not existant? fail
539  if (!pPlr) return false;
540  // network client: don't play here
541  // return true for network sync
542  if (!pPlr->LocalControl) return true;
543  }
544  // even less than nothing?
545  if (iLevel<0) return true;
546  // default sound level
547  if (iLevel.IsNil() || iLevel>100)
548  iLevel=100;
549  // modifier from prop list
550  C4SoundModifier *modifier;
551  if (modifier_props)
552  modifier = Application.SoundSystem.Modifiers.Get(modifier_props, true);
553  else
554  modifier = nullptr;
555  // target object
556  C4Object *pObj = nullptr;
557  if (!fGlobal) pObj = Object(_this);
558  // play/stop?
559  if (iLoop >= 0)
560  {
561  // already playing?
562  C4SoundInstance *inst = GetSoundInstance(FnStringPar(szSound), pObj);
563  if (inst)
564  {
565  // then just update parameters
566  SoundUpdate(inst, iLevel, iPitch);
567  }
568  else
569  {
570  // try to play effect
571  StartSoundEffect(FnStringPar(szSound), !!iLoop, iLevel, pObj, iCustomFalloffDistance, iPitch, modifier);
572  }
573  }
574  else
575  {
576  StopSoundEffect(FnStringPar(szSound), pObj);
577  }
578  // always return true (network safety!)
579  return true;
580 }
581 
582 static bool FnChangeSoundModifier(C4PropList * _this, C4PropList *modifier_props, bool release)
583 {
584  // internal function to be used by sound library: Updates sound modifier
585  C4SoundModifier *modifier = Application.SoundSystem.Modifiers.Get(modifier_props, false);
586  // modifier not found. May be due to savegame resume.
587  // In that case, creation/updates will happen automatically next time Sound() is called
588  // always return true for sync safety because the internal C4SoundModifierList is not synchronized
589  if (!modifier) return true;
590  if (release)
591  modifier->Release();
592  else
593  modifier->Update();
594  return true;
595 }
596 
597 static bool FnSetGlobalSoundModifier(C4PropList * _this, C4PropList *modifier_props, Nillable<long> at_player)
598 {
599  // set modifier to be applied to all future sounds
600  if (at_player.IsNil())
601  {
602  // no player given: Global modifier for all players.
603  Game.SetGlobalSoundModifier(modifier_props);
604  }
605  else
606  {
607  // modifier for all viewports of a player
608  C4Player *plr = ::Players.Get(at_player);
609  if (!plr) return false;
610  plr->SetSoundModifier(modifier_props);
611  }
612  // always true on valid params for sync safety
613  return true;
614 }
615 
616 static bool FnMusic(C4PropList * _this, C4String *szSongname, bool fLoop, long iFadeTime_ms, long max_resume_time_ms)
617 {
618  bool success;
619  if (max_resume_time_ms < 0) return false; // Safety
620  if (!szSongname)
621  {
622  success = Application.MusicSystem.Stop();
623  }
624  else
625  {
626  success = Application.MusicSystem.Play(FnStringPar(szSongname), !!fLoop, iFadeTime_ms, double(max_resume_time_ms)/1000.0);
627  }
628  if (::Control.SyncMode()) return true;
629  return success;
630 }
631 
632 static long FnMusicLevel(C4PropList * _this, long iLevel)
633 {
635 }
636 
637 static long FnSetPlayList(C4PropList * _this, const C4Value & playlist_data, Nillable<long> iAtPlayer, bool fForceSwitch, long iFadeTime_ms, long max_resume_time_ms)
638 {
639  // Safety
640  if (max_resume_time_ms < 0) return 0;
641  // If a player number is provided, set play list for clients where given player is local only
642  if (!iAtPlayer.IsNil() && iAtPlayer != NO_OWNER)
643  {
644  C4Player *at_plr = ::Players.Get(iAtPlayer);
645  if (!at_plr) return 0;
646  if (!at_plr->LocalControl) return 0;
647  }
648  // Playlist might be a string for the new playlist, a proplist with more info, or nil to reset the playlist
649  C4String * szPlayList = playlist_data.getStr();
650  C4PropList *playlist_props = nullptr;
651  if (!szPlayList)
652  {
653  playlist_props = playlist_data.getPropList();
654  if (playlist_props)
655  {
656  szPlayList = playlist_props->GetPropertyStr(P_PlayList);
657  // Update playlist properties
658  C4Value val;
659  if (playlist_props->GetProperty(P_MusicBreakMin, &val)) ::Application.MusicSystem.SetMusicBreakMin(val.getInt());
660  if (playlist_props->GetProperty(P_MusicBreakMax, &val)) ::Application.MusicSystem.SetMusicBreakMax(val.getInt());
663  }
664  }
665  // Set playlist; count entries
666  long iFilesInPlayList = ::Application.MusicSystem.SetPlayList(FnStringPar(szPlayList), fForceSwitch, iFadeTime_ms, double(max_resume_time_ms)/1000.0f);
667  // network/record/replay: return 0 for sync reasons
668  if (::Control.SyncMode()) return 0;
669  return iFilesInPlayList;
670 }
671 
672 static bool FnGameOver(C4PropList * _this, long iGameOverValue /* provided for future compatibility */)
673 {
674  return !!Game.DoGameOver();
675 }
676 
677 static bool FnGainMissionAccess(C4PropList * _this, C4String *szPassword)
678 {
679  if (std::strlen(Config.General.MissionAccess)+std::strlen(FnStringPar(szPassword))+3>CFG_MaxString) return false;
680  SAddModule(Config.General.MissionAccess,FnStringPar(szPassword));
681  return true;
682 }
683 
684 static C4Value FnPlayerMessage(C4PropList * _this, C4Value * Pars)
685 {
686  if (!Object(_this)) throw NeedObjectContext("PlayerMessage");
687  int iPlayer = Pars[0].getInt();
688  C4String * szMessage = Pars[1].getStr();
689  if (!szMessage) return C4VBool(false);
690  StdStrBuf buf;
691  buf.SetLength(szMessage->GetData().getLength());
692 
693  // Speech
694  bool fSpoken=false;
695  if (SCopySegment(FnStringPar(szMessage),1,buf.getMData(),'$'))
696  if (StartSoundEffect(buf.getData(),false,100, Object(_this)))
697  fSpoken=true;
698 
699  // Text
700  if (!fSpoken)
701  {
702  buf.Take(FnStringFormat(_this, szMessage, &Pars[2], 8));
703  const char * dollar = strchr(buf.getData(), '$');
704  if (dollar) buf.Shrink(dollar - buf.getData());
705  GameMsgObjectPlayer(buf.getData(),Object(_this), iPlayer);
706  }
707  return C4VBool(true);
708 }
709 
710 static C4Value FnMessage(C4PropList * _this, C4Value * Pars)
711 {
712  if (!Object(_this)) throw NeedObjectContext("Message");
713  C4String * szMessage = Pars[0].getStr();
714  if (!szMessage) return C4VBool(false);
715  StdStrBuf buf;
716  buf.SetLength(szMessage->GetData().getLength());
717 
718  // Speech
719  bool fSpoken=false;
720  if (SCopySegment(FnStringPar(szMessage),1,buf.getMData(),'$'))
721  if (StartSoundEffect(buf.getData(),false,100, Object(_this)))
722  fSpoken=true;
723 
724  // Text
725  if (!fSpoken)
726  {
727  buf.Take(FnStringFormat(_this,szMessage, &Pars[1], 9));
728  const char * dollar = strchr(buf.getData(), '$');
729  if (dollar) buf.Shrink(dollar - buf.getData());
730  GameMsgObject(buf.getData(),Object(_this));
731  }
732  return C4VBool(true);
733 }
734 
735 // undocumented!
736 static C4Value FnAddMessage(C4PropList * _this, C4Value * Pars)
737 {
738  if (!Object(_this)) throw NeedObjectContext("AddMessage");
739  C4String * szMessage = Pars[0].getStr();
740  if (!szMessage) return C4VBool(false);
741 
742  ::Messages.Append(C4GM_Target, FnStringFormat(_this, szMessage, &Pars[1], 9).getData(),
743  Object(_this),NO_OWNER,0,0,C4RGB(0xff, 0xff, 0xff));
744  return C4VBool(true);
745 }
746 
747 static long FnMaterial(C4PropList * _this, C4String *mat_name)
748 {
749  return ::MaterialMap.Get(FnStringPar(mat_name));
750 }
751 
752 C4Object* FnPlaceVegetation(C4PropList * _this, C4PropList * Def, long iX, long iY, long iWdt, long iHgt, long iGrowth, C4PropList * shape)
753 {
754  if (shape)
755  {
756  // New-style call with scripted shape
757  C4PropList *out_pos = C4PropList::New(nullptr);
758  C4Value vout_pos = C4VPropList(out_pos);
759  return Game.PlaceVegetation(Def, iX, iY, iWdt, iHgt, iGrowth, shape, out_pos);
760  }
761  else
762  {
763  // Call in old-style shape
764  // Local call: relative coordinates
765  if (Object(_this)) { iX += Object(_this)->GetX(); iY += Object(_this)->GetY(); }
766  // Place vegetation
767  return Game.PlaceVegetation(Def, iX, iY, iWdt, iHgt, iGrowth, nullptr, nullptr);
768  }
769 }
770 
772 {
773  return Game.PlaceAnimal(Def? Def : _this);
774 }
775 
776 static bool FnHostile(C4PropList * _this, long iPlr1, long iPlr2, bool fCheckOneWayOnly)
777 {
778  if (fCheckOneWayOnly)
779  {
780  return ::Players.HostilityDeclared(iPlr1,iPlr2);
781  }
782  else
783  return !!Hostile(iPlr1,iPlr2);
784 }
785 
786 static bool FnSetHostility(C4PropList * _this, long iPlr, long iPlr2, bool fHostile, bool fSilent, bool fNoCalls)
787 {
788  C4Player *pPlr = ::Players.Get(iPlr);
789  if (!pPlr) return false;
790  // do rejection test first
791  if (!fNoCalls)
792  {
793  if (!!::Game.GRBroadcast(PSF_RejectHostilityChange, &C4AulParSet(iPlr, iPlr2, fHostile), true, true))
794  return false;
795  }
796  // OK; set hostility
797  bool fOldHostility = ::Players.HostilityDeclared(iPlr, iPlr2);
798  if (!pPlr->SetHostility(iPlr2,fHostile, fSilent)) return false;
799  // calls afterwards
800  ::Game.GRBroadcast(PSF_OnHostilityChange, &C4AulParSet(C4VInt(iPlr), C4VInt(iPlr2), C4VBool(fHostile), C4VBool(fOldHostility)), true);
801  return true;
802 }
803 
804 static bool FnSetPlrView(C4PropList * _this, long iPlr, C4Object *tobj, bool immediate_position)
805 {
806  if (!ValidPlr(iPlr)) return false;
807  ::Players.Get(iPlr)->SetViewMode(C4PVM_Target, tobj, immediate_position);
808  return true;
809 }
810 
811 static long FnGetPlrViewMode(C4PropList * _this, long iPlr)
812 {
813  if (!ValidPlr(iPlr)) return -1;
814  if (::Control.SyncMode()) return -1;
816 }
817 
818 static void FnResetCursorView(C4PropList * _this, long plr, bool immediate_position)
819 {
820  C4Player *pplr = ::Players.Get(plr);
821  if (pplr) pplr->ResetCursorView(immediate_position);
822 }
823 
824 static C4Object *FnGetPlrView(C4PropList * _this, long iPlr)
825 {
826  C4Player *pPlr = ::Players.Get(iPlr);
827  if (!pPlr || pPlr->ViewMode != C4PVM_Target) return nullptr;
828  return pPlr->ViewTarget;
829 }
830 
831 // flags for SetPlayerZoom* calls
832 static const int PLRZOOM_Direct = 0x01,
833  PLRZOOM_NoIncrease = 0x04,
834  PLRZOOM_NoDecrease = 0x08,
835  PLRZOOM_LimitMin = 0x10,
836  PLRZOOM_LimitMax = 0x20,
837  PLRZOOM_Set = 0x40;
838 
839 static bool FnSetPlayerZoomByViewRange(C4PropList * _this, long plr_idx, long range_wdt, long range_hgt, long flags)
840 {
841  // zoom size safety - both ranges 0 is fine, it causes a zoom reset to default
842  if (range_wdt < 0 || range_hgt < 0) return false;
843  // special player NO_OWNER: apply to all viewports
844  if (plr_idx == NO_OWNER)
845  {
846  for (C4Player *plr = ::Players.First; plr; plr=plr->Next)
847  if (plr->Number != NO_OWNER) // can't happen, but would be a crash if it did...
848  FnSetPlayerZoomByViewRange(_this, plr->Number, range_wdt, range_hgt, flags);
849  return true;
850  }
851  else
852  {
853  // safety check on player only, so function return result is always in sync
854  C4Player *plr = ::Players.Get(plr_idx);
855  if (!plr) return false;
856  // adjust values in player
857  if (flags & PLRZOOM_LimitMin) plr->SetMinZoomByViewRange(range_wdt, range_hgt, !!(flags & PLRZOOM_NoIncrease), !!(flags & PLRZOOM_NoDecrease));
858  if (flags & PLRZOOM_LimitMax) plr->SetMaxZoomByViewRange(range_wdt, range_hgt, !!(flags & PLRZOOM_NoIncrease), !!(flags & PLRZOOM_NoDecrease));
859  // set values after setting min/max to ensure old limits don't block new value
860  if ((flags & PLRZOOM_Set) || !(flags & (PLRZOOM_LimitMin | PLRZOOM_LimitMax)))
861  {
862  plr->SetZoomByViewRange(range_wdt, range_hgt, !!(flags & PLRZOOM_Direct), !!(flags & PLRZOOM_NoIncrease), !!(flags & PLRZOOM_NoDecrease));
863  }
864 
865  }
866  return true;
867 }
868 
869 static C4PropList *FnGetPlayerZoomLimits(C4PropList * _this, long plr_idx)
870 {
871  // get player
872  C4Player *plr = ::Players.Get(plr_idx);
873  if (!plr) return nullptr;
874  // collect limits in a prop list
875  // if neither width not height is set for zoom limits, return engine defaults.
876  C4PropList *result = C4PropList::New();
877  if (!result) return nullptr;
878  result->SetPropertyByS(::Strings.RegString("MaxWidth"), C4VInt((plr->ZoomLimitMaxWdt || plr->ZoomLimitMaxHgt) ? plr->ZoomLimitMaxWdt : C4VP_DefMaxViewRangeX));
879  result->SetPropertyByS(::Strings.RegString("MaxHeight"), C4VInt(plr->ZoomLimitMaxHgt));
880  result->SetPropertyByS(::Strings.RegString("MaxValue"), C4VInt(fixtoi(plr->ZoomLimitMaxVal, 100)));
881  result->SetPropertyByS(::Strings.RegString("MinWidth"), C4VInt((plr->ZoomLimitMinWdt || plr->ZoomLimitMinHgt) ? plr->ZoomLimitMinWdt : C4VP_DefMinViewRangeX));
882  result->SetPropertyByS(::Strings.RegString("MinHeight"), C4VInt(plr->ZoomLimitMinHgt));
883  result->SetPropertyByS(::Strings.RegString("MinValue"), C4VInt(fixtoi(plr->ZoomLimitMinVal, 100)));
884  return result;
885 }
886 
887 static bool FnSetPlayerZoom(C4PropList * _this, long plr_idx, long zoom, long precision, long flags)
888 {
889  // parameter safety. 0/0 means "reset to default".
890  if (zoom < 0 || precision < 0) return false;
891  // special player NO_OWNER: apply to all viewports
892  if (plr_idx == NO_OWNER)
893  {
894  for (C4Player *plr = ::Players.First; plr; plr=plr->Next)
895  if (plr->Number != NO_OWNER) // can't happen, but would be a crash if it did...
896  FnSetPlayerZoom(_this, plr->Number, zoom, precision, flags);
897  return true;
898  }
899  else
900  {
901  // zoom factor calculation
902  if (!precision) precision = 1;
903  C4Real fZoom = itofix(zoom, precision);
904  // safety check on player only, so function return result is always in sync
905  C4Player *plr = ::Players.Get(plr_idx);
906  if (!plr) return false;
907  // adjust values in player
908  if (flags & PLRZOOM_LimitMin) plr->SetMinZoom(fZoom, !!(flags & PLRZOOM_NoIncrease), !!(flags & PLRZOOM_NoDecrease));
909  if (flags & PLRZOOM_LimitMax) plr->SetMaxZoom(fZoom, !!(flags & PLRZOOM_NoIncrease), !!(flags & PLRZOOM_NoDecrease));
910  if ((flags & PLRZOOM_Set) || !(flags & (PLRZOOM_LimitMin | PLRZOOM_LimitMax)))
911  {
912  plr->SetZoom(fZoom, !!(flags & PLRZOOM_Direct), !!(flags & PLRZOOM_NoIncrease), !!(flags & PLRZOOM_NoDecrease));
913  }
914 
915  }
916  return true;
917 }
918 
919 static bool FnSetPlayerViewLock(C4PropList * _this, long plr_idx, bool is_locked)
920 {
921  // special player NO_OWNER: apply to all players
922  if (plr_idx == NO_OWNER)
923  {
924  for (C4Player *plr = ::Players.First; plr; plr=plr->Next)
925  if (plr->Number != NO_OWNER) // can't happen, but would be a crash if it did...
926  FnSetPlayerViewLock(_this, plr->Number, is_locked);
927  return true;
928  }
929  C4Player *plr = ::Players.Get(plr_idx);
930  if (!plr) return false;
931  plr->SetViewLocked(is_locked);
932  return true;
933 }
934 
935 static bool FnDoBaseMaterial(C4PropList * _this, long iPlr, C4ID id, long iChange)
936 {
937  // validity check
938  if (!ValidPlr(iPlr)) return false;
939  C4Def *pDef = C4Id2Def(id);
940  if (!pDef) return false;
941  // add to material
942  long iLastcount = ::Players.Get(iPlr)->BaseMaterial.GetIDCount(id);
943  return ::Players.Get(iPlr)->BaseMaterial.SetIDCount(id,iLastcount+iChange,true);
944 }
945 
946 static bool FnDoBaseProduction(C4PropList * _this, long iPlr, C4ID id, long iChange)
947 {
948  // validity check
949  if (!ValidPlr(iPlr)) return false;
950  C4Def *pDef = C4Id2Def(id);
951  if (!pDef) return false;
952  // add to material
953  long iLastcount = ::Players.Get(iPlr)->BaseProduction.GetIDCount(id);
954  return ::Players.Get(iPlr)->BaseProduction.SetIDCount(id,iLastcount+iChange,true);
955 }
956 
957 static bool FnSetPlrKnowledge(C4PropList * _this, Nillable<long> iPlr, C4ID id, bool fRemove)
958 {
959 
960  bool success = false;
961  // iPlr == nil: Call for all players
962  if (iPlr.IsNil())
963  {
964  for (C4Player *player = ::Players.First; player; player = player->Next)
965  if (player->SetKnowledge(id, fRemove))
966  success = true;
967  }
968  else
969  {
970  // Otherwise call for requested player
971  C4Player *player = ::Players.Get(iPlr);
972  if (player) success = player->SetKnowledge(id, fRemove);
973  }
974  return success;
975 }
976 
977 static C4Value FnGetPlrKnowledge(C4PropList * _this, int iPlr, C4ID id, int iIndex, int dwCategory)
978 {
979  if (!ValidPlr(iPlr)) return C4VBool(false);
980  // Search by id, check if available, return bool
981  if (id) return C4VBool(::Players.Get(iPlr)->Knowledge.GetIDCount(id,1) != 0);
982  // Search indexed item of given category, return C4ID
983  return C4VPropList(C4Id2Def(::Players.Get(iPlr)->Knowledge.GetID( ::Definitions, dwCategory, iIndex )));
984 }
985 
986 static C4Def * FnGetDefinition(C4PropList * _this, long iIndex)
987 {
989 }
990 
991 static C4String * FnGetDefinitionGroupPath(C4PropList * _this)
992 {
993  // Must have loaded all paths
994  if (Application.isEditor)
996  // Resolve definition
997  C4Def *def = _this->GetDef();
998  if (!def || !def->ConsoleGroupPath.getData()) return nullptr;
1000 }
1001 
1002 static C4Value FnGetBaseMaterial(C4PropList * _this, int iPlr, C4ID id, int iIndex, int dwCategory)
1003 {
1004  if (!ValidPlr(iPlr)) return C4VBool(false);
1005  // Search by id, return available count
1006  if (id) return C4VInt(::Players.Get(iPlr)->BaseMaterial.GetIDCount(id));
1007  // Search indexed item of given category, return C4ID
1008  return C4VPropList(C4Id2Def(::Players.Get(iPlr)->BaseMaterial.GetID( ::Definitions, dwCategory, iIndex )));
1009 }
1010 
1011 static C4Value FnGetBaseProduction(C4PropList * _this, int iPlr, C4ID id, int iIndex, int dwCategory)
1012 {
1013  if (!ValidPlr(iPlr)) return C4VBool(false);
1014  // Search by id, return available count
1015  if (id) return C4VInt(::Players.Get(iPlr)->BaseProduction.GetIDCount(id));
1016  // Search indexed item of given category, return C4ID
1017  return C4VPropList(C4Id2Def(::Players.Get(iPlr)->BaseProduction.GetID( ::Definitions, dwCategory, iIndex )));
1018 }
1019 
1020 static long FnGetWealth(C4PropList * _this, long iPlr)
1021 {
1022  if (!ValidPlr(iPlr)) return 0;
1023  return ::Players.Get(iPlr)->Wealth;
1024 }
1025 
1026 static bool FnSetWealth(C4PropList * _this, long iPlr, long iValue)
1027 {
1028  if (!ValidPlr(iPlr)) return false;
1029  ::Players.Get(iPlr)->SetWealth(iValue);
1030  return true;
1031 }
1032 
1033 static long FnDoPlayerScore(C4PropList * _this, long iPlr, long iChange)
1034 {
1035  if (!ValidPlr(iPlr)) return false;
1036  return ::Players.Get(iPlr)->DoScore(iChange);
1037 }
1038 
1039 static long FnGetPlayerScore(C4PropList * _this, long iPlr)
1040 {
1041  if (!ValidPlr(iPlr)) return 0;
1043 }
1044 
1045 static long FnGetPlayerScoreGain(C4PropList * _this, long iPlr)
1046 {
1047  if (!ValidPlr(iPlr)) return 0;
1049 }
1050 
1051 static C4Object *FnGetHiRank(C4PropList * _this, long iPlr)
1052 {
1053  if (!ValidPlr(iPlr)) return nullptr;
1055 }
1056 
1057 static C4Object *FnGetCrew(C4PropList * _this, long iPlr, long index)
1058 {
1059  if (!ValidPlr(iPlr)) return nullptr;
1060  return ::Players.Get(iPlr)->Crew.GetObject(index);
1061 }
1062 
1063 static long FnGetCrewCount(C4PropList * _this, long iPlr)
1064 {
1065  if (!ValidPlr(iPlr)) return 0;
1067 }
1068 
1069 static long FnGetPlayerCount(C4PropList * _this, long iType)
1070 {
1071  if (!iType)
1073  else
1075 }
1076 
1077 static long FnGetPlayerByIndex(C4PropList * _this, long iIndex, long iType)
1078 {
1079  C4Player *pPlayer;
1080  if (iType)
1081  pPlayer = ::Players.GetByIndex(iIndex, (C4PlayerType) iType);
1082  else
1083  pPlayer = ::Players.GetByIndex(iIndex);
1084  if (!pPlayer) return NO_OWNER;
1085  return pPlayer->Number;
1086 }
1087 
1088 static long FnEliminatePlayer(C4PropList * _this, long iPlr, bool fRemoveDirect)
1089 {
1090  C4Player *pPlr=::Players.Get(iPlr);
1091  if (!pPlr) return false;
1092  // direct removal?
1093  if (fRemoveDirect)
1094  {
1095  // do direct removal (no fate)
1096  if (::Control.isCtrlHost()) ::Players.CtrlRemove(iPlr, false);
1097  return true;
1098  }
1099  else
1100  {
1101  // do regular elimination
1102  if (pPlr->Eliminated) return false;
1103  pPlr->Eliminate();
1104  }
1105  return true;
1106 }
1107 
1108 // undocumented!
1109 static bool FnSurrenderPlayer(C4PropList * _this, long iPlr)
1110 {
1111  C4Player *pPlr=::Players.Get(iPlr);
1112  if (!pPlr) return false;
1113  if (pPlr->Eliminated) return false;
1114  pPlr->Surrender();
1115  return true;
1116 }
1117 
1118 // undocumented!
1119 static bool FnSetLeaguePerformance(C4PropList * _this, long iScore, long idPlayer)
1120  {
1121  if(!Game.Parameters.isLeague()) return false;
1122  if(idPlayer && !Game.PlayerInfos.GetPlayerInfoByID(idPlayer)) return false;
1123  Game.RoundResults.SetLeaguePerformance(iScore, idPlayer);
1124  return true;
1125  }
1126 
1127 
1128 static const int32_t CSPF_FixedAttributes = 1 << 0,
1129  CSPF_NoScenarioInit = 1 << 1,
1130  CSPF_NoEliminationCheck = 1 << 2,
1131  CSPF_Invisible = 1 << 3,
1132  CSPF_NoScenarioSave = 1 << 4;
1133 
1134 
1135 static bool FnCreateScriptPlayer(C4PropList * _this, C4String *szName, long dwColor, long idTeam, long dwFlags, C4ID idExtra)
1136 {
1137  // safety
1138  if (!szName || !szName->GetData().getLength()) return false;
1139  // this script command puts a new script player info into the list
1140  // the actual join will be delayed and synchronized via queue
1141  // processed by control host only - clients/replay/etc. will perform the join via queue
1142  if (!::Control.isCtrlHost()) return true;
1143  C4PlayerInfo *pScriptPlrInfo = new C4PlayerInfo();
1144  uint32_t dwInfoFlags = 0u;
1145  if (dwFlags & CSPF_FixedAttributes ) dwInfoFlags |= C4PlayerInfo::PIF_AttributesFixed;
1146  if (dwFlags & CSPF_NoScenarioInit ) dwInfoFlags |= C4PlayerInfo::PIF_NoScenarioInit;
1147  if (dwFlags & CSPF_NoEliminationCheck) dwInfoFlags |= C4PlayerInfo::PIF_NoEliminationCheck;
1148  if (dwFlags & CSPF_Invisible ) dwInfoFlags |= C4PlayerInfo::PIF_Invisible;
1149  if (dwFlags & CSPF_NoScenarioSave) dwInfoFlags |= C4PlayerInfo::PIF_NoScenarioSave;
1150  pScriptPlrInfo->SetAsScriptPlayer(szName->GetCStr(), dwColor, dwInfoFlags, idExtra);
1151  pScriptPlrInfo->SetTeam(idTeam);
1152  C4ClientPlayerInfos JoinPkt(nullptr, true, pScriptPlrInfo);
1153  // add to queue!
1155  // always successful for sync reasons
1156  return true;
1157 }
1158 
1159 static C4Object *FnGetCursor(C4PropList * _this, long iPlr)
1160 {
1161  // get player
1162  C4Player *pPlr = ::Players.Get(iPlr);
1163  // invalid player?
1164  if (!pPlr) return nullptr;
1165  return pPlr->Cursor;
1166 }
1167 
1168 // undocumented!
1169 static C4Object *FnGetViewCursor(C4PropList * _this, long iPlr)
1170 {
1171  // get player
1172  C4Player *pPlr = ::Players.Get(iPlr);
1173  // get viewcursor
1174  return pPlr ? pPlr->ViewCursor : nullptr;
1175 }
1176 
1177 static bool FnSetCursor(C4PropList * _this, long iPlr, C4Object *pObj, bool fNoSelectArrow)
1178 {
1179  C4Player *pPlr = ::Players.Get(iPlr);
1180  if (!pPlr || (pObj && !pObj->Status) || (pObj && pObj->CrewDisabled)) return false;
1181  pPlr->SetCursor(pObj, !fNoSelectArrow);
1182  return true;
1183 }
1184 
1185 // undocumented!
1186 static bool FnSetViewCursor(C4PropList * _this, long iPlr, C4Object *pObj)
1187 {
1188  // get player
1189  C4Player *pPlr = ::Players.Get(iPlr);
1190  // invalid player?
1191  if (!pPlr) return false;
1192  // set viewcursor
1193  pPlr->ViewCursor = pObj;
1194  return true;
1195 }
1196 
1197 static long FnGetWind(C4PropList * _this, long x, long y, bool fGlobal)
1198 {
1199  // global wind
1200  if (fGlobal) return ::Weather.Wind;
1201  // local wind
1202  if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
1204 }
1205 
1206 static void FnSetWind(C4PropList * _this, long iWind)
1207 {
1208  ::Weather.SetWind(iWind);
1209 }
1210 
1211 static void FnSetTemperature(C4PropList * _this, long iTemperature)
1212 {
1213  ::Weather.SetTemperature(iTemperature);
1214 }
1215 
1216 static long FnGetTemperature(C4PropList * _this)
1217 {
1219 }
1220 
1221 static void FnSetAmbientBrightness(C4PropList * _this, long iBrightness)
1222 {
1223  if (::Landscape.HasFoW())
1224  ::Landscape.GetFoW()->Ambient.SetBrightness(iBrightness / 100.);
1225 }
1226 
1227 static long FnGetAmbientBrightness(C4PropList * _this)
1228 {
1229  if (!::Landscape.HasFoW())
1230  return 100;
1231  return static_cast<long>(::Landscape.GetFoW()->Ambient.GetBrightness() * 100. + 0.5);
1232 }
1233 
1234 static void FnSetSeason(C4PropList * _this, long iSeason)
1235 {
1236  ::Weather.SetSeason(iSeason);
1237 }
1238 
1239 static long FnGetSeason(C4PropList * _this)
1240 {
1242 }
1243 
1244 static void FnSetClimate(C4PropList * _this, long iClimate)
1245 {
1246  ::Weather.SetClimate(iClimate);
1247 }
1248 
1249 static long FnGetClimate(C4PropList * _this)
1250 {
1252 }
1253 
1254 static long FnLandscapeWidth(C4PropList * _this)
1255 {
1257 }
1258 
1259 static long FnLandscapeHeight(C4PropList * _this)
1260 {
1262 }
1263 
1264 static void FnShakeFree(C4PropList * _this, long x, long y, long rad)
1265 {
1266  ::Landscape.ShakeFree(x,y,rad);
1267 }
1268 
1269 static long FnDigFree(C4PropList * _this, long x, long y, long rad, bool no_dig2objects, bool no_instability_check)
1270 {
1271  return ::Landscape.DigFree(x,y,rad,Object(_this),no_dig2objects,no_instability_check);
1272 }
1273 
1274 static long FnDigFreeRect(C4PropList * _this, long iX, long iY, long iWdt, long iHgt, bool no_dig2objects, bool no_instability_check)
1275 {
1276  return ::Landscape.DigFreeRect(iX,iY,iWdt,iHgt,Object(_this),no_dig2objects,no_instability_check);
1277 }
1278 
1279 static void FnClearFreeRect(C4PropList * _this, long iX, long iY, long iWdt, long iHgt)
1280 {
1281  ::Landscape.ClearFreeRect(iX,iY,iWdt,iHgt);
1282 }
1283 
1284 static bool FnPathFree(C4PropList * _this, long X1, long Y1, long X2, long Y2)
1285 {
1286  return !!PathFree(X1, Y1, X2, Y2);
1287 }
1288 
1289 // undocumented!
1290 static C4ValueArray* FnPathFree2(C4PropList * _this, int32_t x1, int32_t y1, int32_t x2, int32_t y2)
1291 {
1292  int32_t x = -1, y = -1;
1293  if (!PathFree(x1, y1, x2, y2, &x, &y))
1294  {
1295  C4ValueArray *pArray = new C4ValueArray(2);
1296  pArray->SetItem(0, C4VInt(x));
1297  pArray->SetItem(1, C4VInt(y));
1298  return pArray;
1299  }
1300  return nullptr;
1301 }
1302 
1303 C4Object* FnObject(C4PropList * _this, long iNumber)
1304 {
1306  // See FnObjectNumber
1307 }
1308 
1309 static C4Value FnGameCallEx(C4PropList * _this, C4Value * Pars)
1310 {
1311  C4String * fn = Pars[0].getStr();
1312  if (!fn) return C4Value();
1313 
1314  // copy parameters
1315  C4AulParSet ParSet;
1316  ParSet.Copy(&Pars[1], 9);
1317  // Call
1318  return ::Game.GRBroadcast(fn->GetCStr(), &ParSet, true);
1319 }
1320 
1321 static C4Object * FnEditCursor(C4PropList * _this)
1322 {
1323  if (::Control.SyncMode()) return nullptr;
1324  return Console.EditCursor.GetTarget();
1325 }
1326 
1327 static bool FnIsNetwork(C4PropList * _this) { return Game.Parameters.IsNetworkGame; }
1328 
1329 static bool FnIsEditor(C4PropList * _this) { return Game.Parameters.IsEditor; }
1330 
1331 // undocumented!
1332 static C4String *FnGetLeague(C4PropList * _this, long idx)
1333 {
1334  // get indexed league
1335  StdStrBuf sIdxLeague;
1336  if (!Game.Parameters.League.GetSection(idx, &sIdxLeague)) return nullptr;
1337  return String(sIdxLeague.getData());
1338 }
1339 
1340 static int32_t FnGetLeagueScore(C4PropList * _this, long idPlayer)
1341 {
1342  // security
1343  if (idPlayer < 1) return 0;
1344  // get info
1345  C4PlayerInfo *pInfo = Game.PlayerInfos.GetPlayerInfoByID(idPlayer);
1346  if (!pInfo) return 0;
1347  // get league score
1348  return pInfo->getLeagueScore();
1349 }
1350 
1351 static bool FnSetLeagueProgressData(C4PropList * _this, C4String *pNewData, long idPlayer)
1352 {
1353  if(!Game.Parameters.League.getLength() || !idPlayer) return false;
1354  C4PlayerInfo *info = Game.PlayerInfos.GetPlayerInfoByID(idPlayer);
1355  if (!info) return false;
1356  info->SetLeagueProgressData(pNewData ? pNewData->GetCStr() : nullptr);
1357  return true;
1358 }
1359 
1360 static C4String *FnGetLeagueProgressData(C4PropList * _this, long idPlayer)
1361 {
1362  if(!Game.Parameters.League.getLength()) return nullptr;
1363  C4PlayerInfo *info = Game.PlayerInfos.GetPlayerInfoByID(idPlayer);
1364  if (!info) return nullptr;
1365  return String(info->GetLeagueProgressData());
1366 }
1367 
1368 // undocumented!
1369 static bool FnTestMessageBoard(C4PropList * _this, long iForPlr, bool fTestIfInUse)
1370 {
1371  // multi-query-MessageBoard is always available if the player is valid =)
1372  // (but it won't do anything in developer mode...)
1373  C4Player *pPlr = ::Players.Get(iForPlr);
1374  if (!pPlr) return false;
1375  if (!fTestIfInUse) return true;
1376  // single query only if no query is scheduled
1377  return pPlr->HasMessageBoardQuery();
1378 }
1379 
1380 // undocumented!
1381 static bool FnCallMessageBoard(C4PropList * _this, C4Object *pObj, bool fUpperCase, C4String *szQueryString, long iForPlr)
1382 {
1383  if (!pObj) pObj=Object(_this);
1384  if (pObj && !pObj->Status) return false;
1385  // check player
1386  C4Player *pPlr = ::Players.Get(iForPlr);
1387  if (!pPlr) return false;
1388  // remove any previous
1389  pPlr->CallMessageBoard(pObj, StdStrBuf(FnStringPar(szQueryString)), !!fUpperCase);
1390  return true;
1391 }
1392 
1393 // undocumented!
1394 static bool FnAbortMessageBoard(C4PropList * _this, C4Object *pObj, long iForPlr)
1395 {
1396  if (!pObj) pObj=Object(_this);
1397  // check player
1398  C4Player *pPlr = ::Players.Get(iForPlr);
1399  if (!pPlr) return false;
1400  // close TypeIn if active
1401  ::MessageInput.AbortMsgBoardQuery(pObj, iForPlr);
1402  // abort for it
1403  return pPlr->RemoveMessageBoardQuery(pObj);
1404 }
1405 
1406 static void FnSetFoW(C4PropList * _this, bool fEnabled, long iPlr)
1407 {
1408  // safety
1409  if (!ValidPlr(iPlr)) return;
1410  // set enabled
1411  ::Players.Get(iPlr)->SetFoW(!!fEnabled);
1412 }
1413 
1414 static long FnSetMaxPlayer(C4PropList * _this, long iTo)
1415 {
1416  // think positive! :)
1417  if (iTo < 0) return false;
1418  // script functions don't need to pass ControlQueue!
1419  Game.Parameters.MaxPlayers = iTo;
1420  // success
1421  return true;
1422 }
1423 
1424 static bool FnGetMissionAccess(C4PropList * _this, C4String *strMissionAccess)
1425 {
1426  // safety
1427  if (!strMissionAccess) return false;
1428 
1429  // non-sync mode: warn
1430  if (::Control.SyncMode())
1431  Log("Warning: using GetMissionAccess may cause desyncs when playing records!");
1432 
1433  return SIsModule(Config.General.MissionAccess, FnStringPar(strMissionAccess));
1434 }
1435 
1436 // Helper to read or write a value from/to a structure. Must be two
1438 {
1439 public:
1440  C4ValueCompiler(const char **pszNames, int iNameCnt, int iEntryNr)
1441  : pszNames(pszNames), iNameCnt(iNameCnt), iEntryNr(iEntryNr)
1442  { }
1443 
1444  bool isDeserializer() override { return false; }
1445  bool hasNaming() override { return true; }
1446  bool isVerbose() override { return false; }
1447 
1448  bool Name(const char *szName) override
1449  {
1450  // match possible? (no match yet / continued match)
1451  if (!iMatchStart || haveCurrentMatch())
1452  // already got all names?
1453  if (!haveCompleteMatch())
1454  // check name
1455  if (SEqual(pszNames[iMatchCount], szName))
1456  {
1457  // got match
1458  if (!iMatchCount) iMatchStart = iDepth + 1;
1459  iMatchCount++;
1460  }
1461  iDepth++;
1462  return true;
1463  }
1464 
1465  bool Default(const char *szName) override
1466  {
1467  // Always process values even if they are default!
1468  return false;
1469  }
1470 
1471  void NameEnd(bool fBreak = false) override
1472  {
1473  // end of matched name section?
1474  if (haveCurrentMatch())
1475  {
1476  iMatchCount--;
1477  if (!iMatchCount) iMatchStart = 0;
1478  }
1479  iDepth--;
1480  }
1481 
1482  void Begin() override
1483  {
1484  // set up
1485  iDepth = iMatchStart = iMatchCount = 0;
1486  }
1487 
1488 protected:
1489  // value function forward to be overwritten by get or set compiler
1490  virtual void ProcessInt(int32_t &rInt) = 0;
1491  virtual void ProcessBool(bool &rBool) = 0;
1492  virtual void ProcessChar(char &rChar) = 0;
1493  virtual void ProcessString(char *szString, size_t iMaxLength, bool fIsID) = 0;
1494  virtual void ProcessString(char **pszString, bool fIsID) = 0;
1495  virtual void ProcessString(std::string &str, bool isID) = 0;
1496 
1497  // value functions
1498 private:
1499  template<class T>
1500  void MaybeProcessInt(T &t)
1501  {
1502  if (haveCompleteMatch() && !iEntryNr--)
1503  {
1504  int32_t i = t;
1505  ProcessInt(i);
1506  t = i;
1507  }
1508  }
1509 public:
1510  void DWord(int32_t &rInt) override { MaybeProcessInt(rInt); }
1511  void DWord(uint32_t &rInt) override { MaybeProcessInt(rInt); }
1512  void Word(int16_t &rShort) override { MaybeProcessInt(rShort); }
1513  void Word(uint16_t &rShort) override { MaybeProcessInt(rShort); }
1514  void Byte(int8_t &rByte) override { MaybeProcessInt(rByte); }
1515  void Byte(uint8_t &rByte) override { MaybeProcessInt(rByte); }
1516  void Boolean(bool &rBool) override { if (haveCompleteMatch()) if (!iEntryNr--) ProcessBool(rBool); }
1517  void Character(char &rChar) override { if (haveCompleteMatch()) if (!iEntryNr--) ProcessChar(rChar); }
1518 
1519  // The C4ID-Adaptor will set RCT_ID for it's strings (see C4Id.h), so we don't have to guess the type.
1520  void String(char *szString, size_t iMaxLength, RawCompileType eType) override
1521  { if (haveCompleteMatch()) if (!iEntryNr--) ProcessString(szString, iMaxLength, eType == StdCompiler::RCT_ID); }
1522  void String(char **pszString, RawCompileType eType) override
1523  { if (haveCompleteMatch()) if (!iEntryNr--) ProcessString(pszString, eType == StdCompiler::RCT_ID); }
1524  void String(std::string &str, RawCompileType type) override
1525  { if (haveCompleteMatch()) if (!iEntryNr--) ProcessString(str, type == StdCompiler::RCT_ID); }
1526  void Raw(void *pData, size_t iSize, RawCompileType eType = RCT_Escaped) override
1527  { /* C4Script can't handle this */ }
1528 
1529 private:
1530 
1531  // Name(s) of the entry to read
1532  const char **pszNames;
1533  int iNameCnt;
1534  // Number of the element that is to be read
1535  int iEntryNr;
1536 
1537  // current depth
1538  int iDepth;
1539  // match start (where did the first name match?),
1540  // match count (how many names did match, from that point?)
1541  int iMatchStart, iMatchCount;
1542 
1543 private:
1544  // match active?
1545  bool haveCurrentMatch() const { return iDepth + 1 == iMatchStart + iMatchCount; }
1546  // match complete?
1547  bool haveCompleteMatch() const { return haveCurrentMatch() && iMatchCount == iNameCnt; }
1548 };
1549 
1551 {
1552 private:
1553  // Result
1554  C4Value Res;
1555 public:
1556  C4ValueGetCompiler(const char **pszNames, int iNameCnt, int iEntryNr)
1557  : C4ValueCompiler(pszNames, iNameCnt, iEntryNr)
1558  { }
1559 
1560  // Result-getter
1561  const C4Value &getResult() const { return Res; }
1562 
1563 protected:
1564  // get values as C4Value
1565  void ProcessInt(int32_t &rInt) override { Res = C4VInt(rInt); }
1566  void ProcessBool(bool &rBool) override { Res = C4VBool(rBool); }
1567  void ProcessChar(char &rChar) override { Res = C4VString(FormatString("%c", rChar)); }
1568 
1569  void ProcessString(char *szString, size_t iMaxLength, bool fIsID) override
1570  { Res = (fIsID ? C4VPropList(C4Id2Def(C4ID(szString))) : C4VString(szString)); }
1571  void ProcessString(char **pszString, bool fIsID) override
1572  { Res = (fIsID ? C4VPropList(C4Id2Def(C4ID(*pszString))) : C4VString(*pszString)); }
1573  void ProcessString(std::string &str, bool fIsID) override
1574  { Res = (fIsID ? C4VPropList(C4Id2Def(C4ID(str.c_str()))) : C4VString(str.c_str())); }
1575 };
1576 
1577 // Use the compiler to find a named value in a structure
1578 template <class T>
1579 C4Value GetValByStdCompiler(const char *strEntry, const char *strSection, int iEntryNr, const T &rFrom)
1580 {
1581  // Set up name array, create compiler
1582  const char *szNames[2] = { strSection ? strSection : strEntry, strSection ? strEntry : nullptr };
1583  C4ValueGetCompiler Comp(szNames, strSection ? 2 : 1, iEntryNr);
1584 
1585  // Compile
1586  try
1587  {
1588  Comp.Decompile(rFrom);
1589  return Comp.getResult();
1590  }
1591  // Should not happen, catch it anyway.
1592  catch (StdCompiler::Exception *)
1593  {
1594  return C4VNull;
1595  }
1596 }
1597 
1598 static C4Value FnGetDefCoreVal(C4PropList * _this, C4String * strEntry, C4String * strSection, int iEntryNr)
1599 {
1600  if (!_this || !_this->GetDef())
1601  throw NeedNonGlobalContext("GetDefCoreVal");
1602 
1603  return GetValByStdCompiler(FnStringPar(strEntry), strSection ? strSection->GetCStr() : nullptr,
1604  iEntryNr, mkNamingAdapt(*_this->GetDef(), "DefCore"));
1605 }
1606 
1607 static C4Value FnGetObjectVal(C4Object * _this, C4String * strEntry, C4String * strSection, int iEntryNr)
1608 {
1609  // get value
1610  C4ValueNumbers numbers;
1611  C4Value retval = GetValByStdCompiler(FnStringPar(strEntry), strSection ? strSection->GetCStr() : nullptr,
1612  iEntryNr, mkNamingAdapt(mkParAdapt(*Object(_this), &numbers), "Object"));
1613  numbers.Denumerate();
1614  retval.Denumerate(&numbers);
1615  return retval;
1616 }
1617 
1618 static C4Value FnGetObjectInfoCoreVal(C4Object * _this, C4String * strEntry, C4String * strSection, int iEntryNr)
1619 {
1620  // get obj info
1621  C4ObjectInfo* pObjInfo = Object(_this)->Info;
1622 
1623  if (!pObjInfo) return C4VNull;
1624 
1625  // get obj info core
1626  C4ObjectInfoCore* pObjInfoCore = (C4ObjectInfoCore*) pObjInfo;
1627 
1628  // get value
1629  return GetValByStdCompiler(FnStringPar(strEntry), strSection ? strSection->GetCStr() : nullptr,
1630  iEntryNr, mkNamingAdapt(*pObjInfoCore, "ObjectInfo"));
1631 }
1632 
1633 static C4Value FnGetScenarioVal(C4PropList * _this, C4String * strEntry, C4String * strSection, int iEntryNr)
1634 {
1635  return GetValByStdCompiler(FnStringPar(strEntry), strSection ? strSection->GetCStr() : nullptr,
1636  iEntryNr, mkParAdapt(Game.C4S, false));
1637 }
1638 
1639 static C4Value FnGetPlayerVal(C4PropList * _this, C4String * strEntry, C4String * strSection, int iPlayer, int iEntryNr)
1640 {
1641  // get player
1642  C4Player* pPlayer = ::Players.Get(iPlayer);
1643  if (!pPlayer) return C4Value();
1644 
1645  // get value
1646  C4ValueNumbers numbers;
1647  C4Value retval = GetValByStdCompiler(FnStringPar(strEntry), strSection ? strSection->GetCStr() : nullptr,
1648  iEntryNr, mkNamingAdapt(mkParAdapt(*pPlayer, &numbers), "Player"));
1649  numbers.Denumerate();
1650  retval.Denumerate(&numbers);
1651  return retval;
1652 }
1653 
1654 static C4Value FnGetPlayerInfoCoreVal(C4PropList * _this, C4String * strEntry, C4String * strSection, int iPlayer, int iEntryNr)
1655 {
1656  // get player
1657  C4Player* pPlayer = ::Players.Get(iPlayer);
1658  if (!pPlayer) return C4Value();
1659 
1660  // get plr info core
1661  C4PlayerInfoCore* pPlayerInfoCore = (C4PlayerInfoCore*) pPlayer;
1662 
1663  // get value
1664  return GetValByStdCompiler(FnStringPar(strEntry), strSection ? strSection->GetCStr() : nullptr,
1665  iEntryNr, *pPlayerInfoCore);
1666 }
1667 
1668 static C4Value FnGetMaterialVal(C4PropList * _this, C4String * strEntry, C4String* strSection, int iMat, int iEntryNr)
1669 {
1670  if (iMat < 0 || iMat >= ::MaterialMap.Num) return C4Value();
1671 
1672  // get material
1673  C4Material *pMaterial = &::MaterialMap.Map[iMat];
1674 
1675  // get plr info core
1676  C4MaterialCore* pMaterialCore = static_cast<C4MaterialCore*>(pMaterial);
1677 
1678  // get value
1679  return GetValByStdCompiler(FnStringPar(strEntry), strSection ? strSection->GetCStr() : nullptr, iEntryNr, *pMaterialCore);
1680 }
1681 
1682 static C4String *FnMaterialName(C4PropList * _this, long iMat)
1683 {
1684  // mat valid?
1685  if (!MatValid(iMat)) return nullptr;
1686  // return mat name
1687  return String(::MaterialMap.Map[iMat].Name);
1688 }
1689 
1690 static bool FnSetSky(C4PropList * _this, C4String * name)
1691 {
1692  if (!name) return false;
1693  auto& sky = ::Landscape.GetSky();
1694 
1695  // Open Graphics.ocg -- we might need to fetch some shader (slices)
1696  // from there when reloading the sky.
1697  if (!::GraphicsResource.RegisterGlobalGraphics()) return false;
1698  if (!::GraphicsResource.RegisterMainGroups()) return false;
1699 
1700  sky.Clear();
1701  const bool result = sky.Init(false, name->GetCStr());
1702 
1703  // close Graphics.ocg again
1705 
1706  return result;
1707 }
1708 
1709 static bool FnSetSkyAdjust(C4PropList * _this, long dwAdjust, long dwBackClr)
1710 {
1711  // set adjust
1712  ::Landscape.GetSky().SetModulation(dwAdjust, dwBackClr);
1713  // success
1714  return true;
1715 }
1716 
1717 static bool FnSetMatAdjust(C4PropList * _this, long dwAdjust)
1718 {
1719  // set adjust
1720  ::Landscape.SetModulation(dwAdjust);
1721  // success
1722  return true;
1723 }
1724 
1725 static long FnGetSkyAdjust(C4PropList * _this, bool fBackColor)
1726 {
1727  // get adjust
1728  return ::Landscape.GetSky().GetModulation(!!fBackColor);
1729 }
1730 
1731 static long FnGetMatAdjust(C4PropList * _this)
1732 {
1733  // get adjust
1735 }
1736 
1737 static long FnGetTime(C4PropList * _this)
1738 {
1739  // check network, record, etc
1740  if (::Control.SyncMode()) return 0;
1741  return C4TimeMilliseconds::Now().AsInt();
1742 }
1743 
1744 static C4Value FnSetPlrExtraData(C4PropList * _this, int iPlayer, C4String * DataName, const C4Value & Data)
1745 {
1746  const char * strDataName = FnStringPar(DataName);
1747  // do not allow data type C4V_Array or C4V_C4Object
1748  if (Data.GetType() != C4V_Nil &&
1749  Data.GetType() != C4V_Int &&
1750  Data.GetType() != C4V_Bool &&
1751  Data.GetType() != C4V_String) return C4VNull;
1752  C4Player* pPlayer = ::Players.Get(iPlayer);
1753  if (!pPlayer) return C4Value();
1754  // no name list created yet?
1755  if (!pPlayer->ExtraData.pNames)
1756  // create name list
1757  pPlayer->ExtraData.CreateTempNameList();
1758  // data name already exists?
1759  long ival;
1760  if ((ival = pPlayer->ExtraData.pNames->GetItemNr(strDataName)) != -1)
1761  pPlayer->ExtraData[ival] = Data;
1762  else
1763  {
1764  // add name
1765  pPlayer->ExtraData.pNames->AddName(strDataName);
1766  // get val id & set
1767  if ((ival = pPlayer->ExtraData.pNames->GetItemNr(strDataName)) == -1) return C4Value();
1768  pPlayer->ExtraData[ival] = Data;
1769  }
1770  // ok, return the value that has been set
1771  return Data;
1772 }
1773 
1774 static C4Value FnGetPlrExtraData(C4PropList * _this, int iPlayer, C4String * DataName)
1775 {
1776  const char *strDataName = FnStringPar(DataName);
1777  C4Player* pPlayer = ::Players.Get(iPlayer);
1778  if (!pPlayer) return C4Value();
1779  // no name list?
1780  if (!pPlayer->ExtraData.pNames) return C4Value();
1781  long ival;
1782  if ((ival = pPlayer->ExtraData.pNames->GetItemNr(strDataName)) == -1) return C4Value();
1783  // return data
1784  return pPlayer->ExtraData[ival];
1785 }
1786 
1787 // undocumented!
1788 static long FnDrawMatChunks(C4PropList * _this, long tx, long ty, long twdt, long thgt, long icntx, long icnty, C4String *strMaterial, C4String *strTexture, bool bIFT)
1789 {
1790  return ::Landscape.DrawChunks(tx, ty, twdt, thgt, icntx, icnty, FnStringPar(strMaterial), FnStringPar(strTexture), bIFT != 0);
1791 }
1792 
1793 static long FnDrawMap(C4PropList * _this, long iX, long iY, long iWdt, long iHgt, C4String *szMapDef)
1794 {
1795  // draw it!
1796  // don't clear the old map before drawing
1797  return ::Landscape.DrawMap(iX, iY, iWdt, iHgt, FnStringPar(szMapDef), true);
1798 }
1799 
1800 static long FnDrawDefMap(C4PropList * _this, long iX, long iY, long iWdt, long iHgt, C4String *szMapDef)
1801 {
1802  // draw it!
1803  // don't clear the old map before drawing
1804  return ::Landscape.DrawDefMap(iX, iY, iWdt, iHgt, FnStringPar(szMapDef), true);
1805 }
1806 
1807 static bool FnCreateParticle(C4PropList * _this, C4String *name, C4Value x, C4Value y, C4Value speedX, C4Value speedY, C4Value lifetime, C4PropList *properties, int amount)
1808 {
1809  // safety
1810  C4Object *obj = Object(_this);
1811  if (obj && !_this->Status) return false;
1812 #ifndef USE_CONSOLE
1813  if (amount <= 0) amount = 1;
1814 
1815  // get particle
1816  C4ParticleDef *pDef = ::Particles.definitions.GetDef(FnStringPar(name));
1817  if (!pDef) return false;
1818  // construct data
1819  C4ParticleValueProvider valueX, valueY, valueSpeedX, valueSpeedY, valueLifetime;
1820  valueX.Set(x);
1821  valueY.Set(y);
1822  valueSpeedX.Set(speedX);
1823  valueSpeedY.Set(speedY);
1824  valueLifetime.Set(lifetime);
1825  // create
1826  ::Particles.Create(pDef, valueX, valueY, valueSpeedX, valueSpeedY, valueLifetime, properties, amount, obj);
1827 #endif
1828  // success, even if not created
1829  return true;
1830 }
1831 
1832 static bool FnClearParticles(C4PropList * _this)
1833 {
1834 #ifndef USE_CONSOLE
1835  C4Object *obj;
1836  if ((obj = Object(_this)))
1837  {
1838  if (obj->BackParticles)
1839  obj->BackParticles->Clear();
1840  if (obj->FrontParticles)
1841  obj->FrontParticles->Clear();
1842  }
1843  else
1844  {
1845  if (::Particles.GetGlobalParticles())
1847  }
1848 #endif
1849  // always return true
1850  return true;
1851 }
1852 
1853 static C4ValueArray* FnPV_Linear(C4PropList * _this, C4Value startValue, C4Value endValue)
1854 {
1855  C4ValueArray *pArray = new C4ValueArray(3);
1856  pArray->SetItem(0, C4VInt(C4PV_Linear));
1857  pArray->SetItem(1, startValue);
1858  pArray->SetItem(2, endValue);
1859  return pArray;
1860 }
1861 
1862 static C4ValueArray* FnPV_Random(C4PropList * _this, C4Value startValue, C4Value endValue, C4Value rerollInterval, C4Value seed)
1863 {
1864  C4ValueArray *pArray = new C4ValueArray(4);
1865  pArray->SetItem(0, C4VInt(C4PV_Random));
1866  pArray->SetItem(1, startValue);
1867  pArray->SetItem(2, endValue);
1868  pArray->SetItem(3, rerollInterval);
1869  pArray->SetItem(4, seed);
1870  return pArray;
1871 }
1872 
1873 static C4ValueArray* FnPV_Direction(C4PropList * _this, C4Value factor)
1874 {
1875  C4ValueArray *pArray = new C4ValueArray(2);
1876  pArray->SetItem(0, C4VInt(C4PV_Direction));
1877  pArray->SetItem(1, factor.GetType() != C4V_Nil ? factor : C4VInt(1000));
1878  return pArray;
1879 }
1880 
1881 static C4ValueArray* FnPV_Step(C4PropList * _this, C4Value step, C4Value startValue, C4Value delay, C4Value maximumValue)
1882 {
1883  C4ValueArray *pArray = new C4ValueArray(5);
1884  pArray->SetItem(0, C4VInt(C4PV_Step));
1885  pArray->SetItem(1, step);
1886  pArray->SetItem(2, startValue);
1887  pArray->SetItem(3, delay);
1888  pArray->SetItem(4, maximumValue);
1889  return pArray;
1890 }
1891 
1892 static C4Value FnPV_KeyFrames(C4PropList * _this, C4Value *pars)
1893 {
1894  C4ValueArray *pArray = new C4ValueArray(C4AUL_MAX_Par);
1895  pArray->SetItem(0, C4VInt(C4PV_KeyFrames));
1896  const int offset = 1;
1897 
1898  // Read all parameters
1899  int i = 0;
1900  for (; i < C4AUL_MAX_Par; i++)
1901  {
1902  C4Value Data = *(pars++);
1903  // No data given?
1904  if (Data.GetType() == C4V_Nil) break;
1905 
1906  pArray->SetItem(offset + i, Data);
1907  }
1908  pArray->SetSize(i + offset);
1909  return C4Value(pArray);
1910 }
1911 
1912 static C4ValueArray* FnPV_Sin(C4PropList * _this, C4Value value, C4Value amplitude, C4Value offset)
1913 {
1914  C4ValueArray *pArray = new C4ValueArray(5);
1915  pArray->SetItem(0, C4VInt(C4PV_Sin));
1916  pArray->SetItem(1, value);
1917  pArray->SetItem(2, amplitude);
1918  pArray->SetItem(3, offset);
1919  return pArray;
1920 }
1921 
1922 static C4ValueArray* FnPV_Cos(C4PropList * _this, C4Value value, C4Value amplitude, C4Value offset)
1923 {
1924  C4ValueArray *pArray = new C4ValueArray(5);
1925  pArray->SetItem(0, C4VInt(C4PV_Cos));
1926  pArray->SetItem(1, value);
1927  pArray->SetItem(2, amplitude);
1928  pArray->SetItem(3, offset);
1929  return pArray;
1930 }
1931 
1932 static C4ValueArray* FnPV_Speed(C4PropList * _this, C4Value factor, C4Value startValue)
1933 {
1934  C4ValueArray *pArray = new C4ValueArray(3);
1935  pArray->SetItem(0, C4VInt(C4PV_Speed));
1936  pArray->SetItem(1, factor.GetType() == C4V_Nil ? C4VInt(1000) : factor);
1937  pArray->SetItem(2, startValue);
1938  return pArray;
1939 }
1940 
1941 static C4ValueArray* FnPV_Wind(C4PropList * _this, C4Value factor, C4Value startValue)
1942 {
1943  C4ValueArray *pArray = new C4ValueArray(3);
1944  pArray->SetItem(0, C4VInt(C4PV_Wind));
1945  pArray->SetItem(1, factor.GetType() == C4V_Nil ? C4VInt(1000) : factor);
1946  pArray->SetItem(2, startValue);
1947  return pArray;
1948 }
1949 
1950 static C4ValueArray* FnPV_Gravity(C4PropList * _this, C4Value factor, C4Value startValue)
1951 {
1952  C4ValueArray *pArray = new C4ValueArray(3);
1953  pArray->SetItem(0, C4VInt(C4PV_Gravity));
1954  pArray->SetItem(1, factor.GetType() == C4V_Nil ? C4VInt(1000) : factor);
1955  pArray->SetItem(2, startValue);
1956  return pArray;
1957 }
1958 
1959 static C4ValueArray* FnPC_Die(C4PropList * _this)
1960 {
1961  C4ValueArray *pArray = new C4ValueArray(1);
1962  pArray->SetItem(0, C4VInt(C4PC_Die));
1963  return pArray;
1964 }
1965 
1966 static C4ValueArray* FnPC_Bounce(C4PropList * _this, C4Value bouncyness)
1967 {
1968  C4ValueArray *pArray = new C4ValueArray(2);
1969  pArray->SetItem(0, C4VInt(C4PC_Bounce));
1970  pArray->SetItem(1, bouncyness.GetType() != C4V_Nil ? bouncyness : C4VInt(1000));
1971  return pArray;
1972 }
1973 
1974 static C4ValueArray* FnPC_Stop(C4PropList * _this)
1975 {
1976  C4ValueArray *pArray = new C4ValueArray(1);
1977  pArray->SetItem(0, C4VInt(C4PC_Stop));
1978  return pArray;
1979 }
1980 
1981 static bool FnSetSkyParallax(C4PropList * _this, Nillable<long> iMode, Nillable<long> iParX, Nillable<long> iParY, Nillable<long> iXDir, Nillable<long> iYDir, Nillable<long> iX, Nillable<long> iY)
1982 {
1983  // set all parameters that aren't nil
1984  if (!iMode.IsNil())
1985  if (Inside<long>(iMode, 0, 1)) ::Landscape.GetSky().ParallaxMode = iMode;
1986  if (!iParX.IsNil() && iParX) ::Landscape.GetSky().ParX = iParX;
1987  if (!iParY.IsNil() && iParY) ::Landscape.GetSky().ParY = iParY;
1988  if (!iXDir.IsNil()) ::Landscape.GetSky().xdir = itofix(iXDir);
1989  if (!iYDir.IsNil()) ::Landscape.GetSky().ydir = itofix(iYDir);
1990  if (!iX.IsNil()) ::Landscape.GetSky().x = itofix(iX);
1991  if (!iY.IsNil()) ::Landscape.GetSky().y = itofix(iY);
1992  // success
1993  return true;
1994 }
1995 
1996 static long FnReloadDef(C4PropList * _this, C4ID idDef, long iReloadWhat)
1997 {
1998  // get def
1999  C4Def *pDef=nullptr;
2000  if (!idDef)
2001  {
2002  // no def given: local def
2003  if (Object(_this)) pDef=Object(_this)->Def;
2004  }
2005  else
2006  // def by ID
2007  pDef=::Definitions.ID2Def(idDef);
2008  // safety
2009  if (!pDef) return false;
2010  // reload everything if nothing has been specified
2011  if (!iReloadWhat) iReloadWhat=C4D_Load_RX;
2012  // perform reload
2013  return Game.ReloadDef(pDef->id);
2014 }
2015 
2016 static long FnReloadParticle(C4PropList * _this, C4String *szParticleName)
2017 {
2018  // perform reload
2019  return Game.ReloadParticle(FnStringPar(szParticleName));
2020 }
2021 
2022 static bool FnSetGamma(C4PropList * _this, long iRed, long iGreen, long iBlue, long iRampIndex)
2023 {
2024  pDraw->SetGamma(float(iRed) / 100,
2025  float(iGreen) / 100,
2026  float(iBlue) / 100,
2027  iRampIndex);
2028  return true;
2029 }
2030 
2031 static bool FnResetGamma(C4PropList * _this, long iRampIndex)
2032 {
2034  return true;
2035 }
2036 
2037 static Nillable<long> FnAddFragmentShader(C4PropList * _this, C4String * name, C4String * shader)
2038 {
2039  if (!name || !shader) return C4Void();
2040  return ScriptShader.Add(name->GetCStr(), C4ScriptShader::FragmentShader, shader->GetCStr());
2041 }
2042 
2043 static bool FnRemoveShader(C4PropList * _this, long id)
2044 {
2045  return ScriptShader.Remove(id);
2046 }
2047 
2048 // undocumented!
2049 static long FnFrameCounter(C4PropList * _this) { return Game.FrameCounter; }
2050 
2051 struct PathInfo
2052 {
2053  long ilx, ily;
2054  long ilen;
2055 };
2056 
2058 {
2059  explicit SumPathLength(PathInfo *info) : pPathInfo(info) {}
2060  bool operator()(int32_t iX, int32_t iY, C4Object *TransferTarget)
2061  {
2062  pPathInfo->ilen += Distance(pPathInfo->ilx, pPathInfo->ily, iX, iY);
2063  pPathInfo->ilx = iX;
2064  pPathInfo->ily = iY;
2065  return true;
2066  }
2067 
2068 private:
2069  PathInfo *pPathInfo;
2070 };
2071 
2072 static Nillable<long> FnGetPathLength(C4PropList * _this, long iFromX, long iFromY, long iToX, long iToY, long iLevel)
2073 {
2075  PathInfo.ilx = iFromX;
2076  PathInfo.ily = iFromY;
2077  PathInfo.ilen = 0;
2078  if (!iLevel)
2079  iLevel = 1;
2080  Game.PathFinder.SetLevel(iLevel);
2081  if (!Game.PathFinder.Find(iFromX, iFromY, iToX, iToY, SumPathLength(&PathInfo)))
2082  return C4Void();
2083  return PathInfo.ilen + Distance(PathInfo.ilx, PathInfo.ily, iToX, iToY);
2084 }
2085 
2086 // undocumented!
2087 static long FnSetTextureIndex(C4PropList * _this, C4String *psMatTex, long iNewIndex, bool fInsert)
2088 {
2089  if (!Inside(iNewIndex, 0l, 255l)) return false;
2090  return ::Landscape.SetTextureIndex(FnStringPar(psMatTex), BYTE(iNewIndex), !!fInsert);
2091 }
2092 
2093 // undocumented!
2094 static long FnRemoveUnusedTexMapEntries(C4PropList * _this)
2095 {
2097  return true;
2098 }
2099 
2100 static const int32_t DMQ_Sky = 0, // draw w/ sky IFT
2101  DMQ_Sub = 1, // draw w/ tunnel IFT
2102  DMQ_Bridge = 2; // draw only over materials you can bridge over
2103 
2104 static bool FnDrawMaterialQuad(C4PropList * _this, C4String *szMaterial, long iX1, long iY1, long iX2, long iY2, long iX3, long iY3, long iX4, long iY4, const C4Value& draw_mode)
2105 {
2106  const char *szMat = FnStringPar(szMaterial);
2107 
2108  const char *szBackMat = nullptr;
2109  bool fBridge = false;
2110  if (draw_mode.GetType() == C4V_Int)
2111  {
2112  // Default behaviour: Default background material
2113  const int draw_mode_value = draw_mode.getInt();
2114  switch(draw_mode_value)
2115  {
2116  case DMQ_Sky: break;
2117  case DMQ_Sub: szBackMat = "Tunnel"; break; // TODO: Go via DefaultBkgMat
2118  case DMQ_Bridge: fBridge = true; break;
2119  }
2120  }
2121  else if (draw_mode.GetType() == C4V_String)
2122  {
2123  szBackMat = FnStringPar(draw_mode.getStr());
2124  }
2125 
2126  return !! ::Landscape.DrawQuad(iX1, iY1, iX2, iY2, iX3, iY3, iX4, iY4, szMat, szBackMat, fBridge);
2127 }
2128 
2129 static bool FnSetFilmView(C4PropList * _this, long iToPlr)
2130 {
2131  // check player
2132  if (!ValidPlr(iToPlr) && iToPlr != NO_OWNER) return false;
2133  // real switch in replays only
2134  if (!::Control.isReplay()) return true;
2135  // set new target plr
2136  if (C4Viewport *vp = ::Viewports.GetFirstViewport()) vp->Init(iToPlr, true);
2137  // done, always success (sync)
2138  return true;
2139 }
2140 
2141 static bool FnAddMsgBoardCmd(C4PropList * _this, C4String *pstrCommand, C4String *pstrScript)
2142 {
2143  // safety
2144  if (!pstrCommand || !pstrScript) return false;
2145  // add command
2146  ::MessageInput.AddCommand(FnStringPar(pstrCommand), FnStringPar(pstrScript));
2147  return true;
2148 }
2149 
2150 static bool FnSetGameSpeed(C4PropList * _this, long iSpeed)
2151 {
2152  // safety
2153  if (iSpeed) if (!Inside<long>(iSpeed, 0, 1000)) return false;
2154  if (!iSpeed) iSpeed = 38;
2155  // set speed, restart timer
2156  Application.SetGameTickDelay(1000 / iSpeed);
2157  return true;
2158 }
2159 
2160 bool SimFlight(C4Real &x, C4Real &y, C4Real &xdir, C4Real &ydir, int32_t iDensityMin, int32_t iDensityMax, int32_t &iIter);
2161 
2162 static C4ValueArray* FnSimFlight(C4PropList * _this, int X, int Y, Nillable<int> pvrXDir, Nillable<int> pvrYDir, Nillable<int> pviDensityMin, Nillable<int> pviDensityMax, Nillable<int> pviIter, int iPrec)
2163 {
2164  // check and set parameters
2165  if (Object(_this))
2166  {
2167  X += Object(_this)->GetX();
2168  Y += Object(_this)->GetY();
2169  }
2170  int XDir = pvrXDir.IsNil() && Object(_this) ? fixtoi(Object(_this)->xdir) : static_cast<int>(pvrXDir);
2171  int YDir = pvrXDir.IsNil() && Object(_this) ? fixtoi(Object(_this)->ydir) : static_cast<int>(pvrYDir);
2172 
2173  int iDensityMin = pviDensityMin.IsNil() ? C4M_Solid : static_cast<int>(pviDensityMin);
2174  int iDensityMax = pviDensityMax.IsNil() ? 100 : static_cast<int>(pviDensityMax);
2175  int iIter = pviIter.IsNil() ? -1 : static_cast<int>(pviIter);
2176  if (!iPrec) iPrec = 10;
2177 
2178  // convert to C4Real
2179  C4Real x = itofix(X), y = itofix(Y),
2180  xdir = itofix(XDir, iPrec), ydir = itofix(YDir, iPrec);
2181 
2182  // simulate
2183  if (!SimFlight(x, y, xdir, ydir, iDensityMin, iDensityMax, iIter))
2184  {
2185  iIter *= -1;
2186  }
2187 
2188  // write results to array
2189  C4ValueArray *pResults = new C4ValueArray(5);
2190  pResults->SetItem(0, C4VInt(fixtoi(x)));
2191  pResults->SetItem(1, C4VInt(fixtoi(y)));
2192  pResults->SetItem(2, C4VInt(fixtoi(xdir * iPrec)));
2193  pResults->SetItem(3, C4VInt(fixtoi(ydir * iPrec)));
2194  pResults->SetItem(4, C4VInt(iIter));
2195  return pResults;
2196 }
2197 
2198 // undocumented!
2199 static long FnLoadScenarioSection(C4PropList * _this, C4String *pstrSection, long dwFlags)
2200 {
2201  // safety
2202  const char *szSection;
2203  if (!pstrSection || !*(szSection=FnStringPar(pstrSection))) return false;
2204  // try to load it
2205  return Game.LoadScenarioSection(szSection, dwFlags);
2206 }
2207 
2208 static bool FnSetViewOffset(C4PropList * _this, long iPlayer, long iX, long iY)
2209 {
2210  if (!ValidPlr(iPlayer)) return false;
2211  // get player viewport
2212  C4Viewport *pView = ::Viewports.GetViewport(iPlayer);
2213  if (!pView) return true; // sync safety
2214  // set
2215  pView->SetViewOffset(iX, iY);
2216  // ok
2217  return true;
2218 }
2219 
2220 // undocumented!
2221 static bool FnSetPreSend(C4PropList * _this, long iToVal, C4String *pNewName)
2222 {
2223  if (!::Control.isNetwork()) return true;
2224  // dbg: manual presend
2225  const char *szClient = FnStringPar(pNewName);
2226  if (!szClient || !*szClient || WildcardMatch(szClient, Game.Clients.getLocalName()))
2227  {
2228  ::Control.Network.setTargetFPS(iToVal);
2229  ::GraphicsSystem.FlashMessage(FormatString("TargetFPS: %ld", iToVal).getData());
2230  }
2231  return true;
2232 }
2233 
2234 static long FnGetPlayerID(C4PropList * _this, long iPlayer)
2235 {
2236  C4Player *pPlr = ::Players.Get(iPlayer);
2237  return pPlr ? pPlr->ID : 0;
2238 }
2239 
2240 static long FnGetPlayerTeam(C4PropList * _this, long iPlayer)
2241 {
2242  // get player
2243  C4Player *pPlr = ::Players.Get(iPlayer);
2244  if (!pPlr) return 0;
2245  // search team containing this player
2246  C4Team *pTeam = Game.Teams.GetTeamByPlayerID(pPlr->ID);
2247  if (pTeam) return pTeam->GetID();
2248  // special value of -1 indicating that the team is still to be chosen
2249  if (pPlr->IsChosingTeam()) return -1;
2250  // No team.
2251  return 0;
2252 }
2253 
2254 static bool FnSetPlayerTeam(C4PropList * _this, long iPlayer, long idNewTeam, bool fNoCalls)
2255 {
2256  // no team changing in league games
2257  if (Game.Parameters.isLeague()) return false;
2258  // get player
2259  C4Player *pPlr = ::Players.Get(iPlayer);
2260  if (!pPlr) return false;
2261  C4PlayerInfo *pPlrInfo = pPlr->GetInfo();
2262  if (!pPlrInfo) return false;
2263  // already in that team?
2264  if (pPlr->Team == idNewTeam) return true;
2265  // ask team setting if it's allowed (also checks for valid team)
2266  if (!Game.Teams.IsJoin2TeamAllowed(idNewTeam, pPlrInfo->GetType())) return false;
2267  // ask script if it's allowed
2268  if (!fNoCalls)
2269  {
2270  if (!!::Game.GRBroadcast(PSF_RejectTeamSwitch, &C4AulParSet(iPlayer, idNewTeam), true, true))
2271  return false;
2272  }
2273  // exit previous team
2274  C4Team *pOldTeam = Game.Teams.GetTeamByPlayerID(pPlr->ID);
2275  int32_t idOldTeam = 0;
2276  if (pOldTeam)
2277  {
2278  idOldTeam = pOldTeam->GetID();
2279  pOldTeam->RemovePlayerByID(pPlr->ID);
2280  }
2281  // enter new team
2282  if (idNewTeam)
2283  {
2284  C4Team *pNewTeam = Game.Teams.GetGenerateTeamByID(idNewTeam);
2285  if (pNewTeam)
2286  {
2287  pNewTeam->AddPlayer(*pPlrInfo, true);
2288  idNewTeam = pNewTeam->GetID();
2289  }
2290  else
2291  {
2292  // unknown error
2293  pPlr->Team = idNewTeam = 0;
2294  }
2295  }
2296  // update hositlities if this is not a "silent" change
2297  if (!fNoCalls)
2298  {
2299  pPlr->SetTeamHostility();
2300  }
2301  // do callback to reflect change in scenario
2302  if (!fNoCalls)
2303  ::Game.GRBroadcast(PSF_OnTeamSwitch, &C4AulParSet(iPlayer, idNewTeam, idOldTeam), true);
2304  return true;
2305 }
2306 
2307 // undocumented!
2308 static C4PropList *FnGetScriptPlayerExtraID(C4PropList * _this, long player_number)
2309 {
2310  C4Player *plr = ::Players.Get(player_number);
2311  if (!plr) return nullptr;
2312  C4PlayerInfo *info = plr->GetInfo();
2313  if (!info) return nullptr;
2314  return C4Id2Def(info->GetScriptPlayerExtraID());
2315 }
2316 
2317 // undocumented!
2318 static long FnGetTeamConfig(C4PropList * _this, long iConfigValue)
2319 {
2320  // query value
2321  switch (iConfigValue)
2322  {
2323  case C4TeamList::TEAM_Custom: return Game.Teams.IsCustom();
2330  }
2331  // undefined value
2332  DebugLogF("GetTeamConfig: Unknown config value: %ld", iConfigValue);
2333  return 0;
2334 }
2335 
2336 static C4String *FnGetTeamName(C4PropList * _this, long iTeam)
2337 {
2338  C4Team *pTeam = Game.Teams.GetTeamByID(iTeam);
2339  if (!pTeam) return nullptr;
2340  return String(pTeam->GetName());
2341 }
2342 
2343 static long FnGetTeamColor(C4PropList * _this, long iTeam)
2344 {
2345  C4Team *pTeam = Game.Teams.GetTeamByID(iTeam);
2346  return pTeam ? pTeam->GetColor() : 0u;
2347 }
2348 
2349 static long FnGetTeamByIndex(C4PropList * _this, long iIndex)
2350 {
2351  C4Team *pTeam = Game.Teams.GetTeamByIndex(iIndex);
2352  return pTeam ? pTeam->GetID() : 0;
2353 }
2354 
2355 static long FnGetTeamCount(C4PropList * _this)
2356 {
2357  return Game.Teams.GetTeamCount();
2358 }
2359 
2360 // undocumented!
2361 static bool FnInitScenarioPlayer(C4PropList * _this, long iPlayer, long idTeam)
2362 {
2363  C4Player *pPlr = ::Players.Get(iPlayer);
2364  if (!pPlr) return false;
2365  return pPlr->ScenarioAndTeamInit(idTeam);
2366 }
2367 
2368 static bool FnSetScoreboardData(C4PropList * _this, long iRowID, long iColID, C4String *pText, long iData)
2369 {
2370  Game.Scoreboard.SetCell(iColID, iRowID, pText ? pText->GetCStr() : nullptr, iData);
2371  return true;
2372 }
2373 
2374 // undocumented!
2375 static C4String *FnGetScoreboardString(C4PropList * _this, long iRowID, long iColID)
2376 {
2377  return String(Game.Scoreboard.GetCellString(iColID, iRowID));
2378 }
2379 
2380 // undocumented!
2381 static int32_t FnGetScoreboardData(C4PropList * _this, long iRowID, long iColID)
2382 {
2383  return Game.Scoreboard.GetCellData(iColID, iRowID);
2384 }
2385 
2386 static bool FnDoScoreboardShow(C4PropList * _this, long iChange, long iForPlr)
2387 {
2388  C4Player *pPlr;
2389  if (iForPlr)
2390  {
2391  // abort if the specified player is not local - but always return if the player exists,
2392  // to ensure sync safety
2393  if (!(pPlr = ::Players.Get(iForPlr-1))) return false;
2394  if (!pPlr->LocalControl) return true;
2395  }
2396  Game.Scoreboard.DoDlgShow(iChange, false);
2397  return true;
2398 }
2399 
2400 static bool FnSortScoreboard(C4PropList * _this, long iByColID, bool fReverse)
2401 {
2402  return Game.Scoreboard.SortBy(iByColID, !!fReverse);
2403 }
2404 
2405 // undocumented!
2406 static bool FnAddEvaluationData(C4PropList * _this, C4String *pText, long idPlayer)
2407 {
2408  // safety
2409  if (!pText) return false;
2410  if (!pText->GetCStr()) return false;
2411  if (idPlayer && !Game.PlayerInfos.GetPlayerInfoByID(idPlayer)) return false;
2412  // add data
2413  Game.RoundResults.AddCustomEvaluationString(pText->GetCStr(), idPlayer);
2414  return true;
2415 }
2416 
2417 // undocumented!
2418 static void FnHideSettlementScoreInEvaluation(C4PropList * _this, bool fHide)
2419 {
2421 }
2422 
2423 static bool FnCustomMessage(C4PropList * _this, C4String *pMsg, C4Object *pObj, Nillable<long> iOwner, long iOffX, long iOffY, long dwClr, C4ID idDeco, C4PropList *pSrc, long dwFlags, long iHSize)
2424 {
2425  // safeties: for global messages pSrc needs to be object/definition. For object-local messages, any proplist is OK
2426  if (pSrc)
2427  if(!pSrc->GetDef() && !pSrc->GetObject() && !pSrc->GetPropertyPropList(P_Source) && !pObj) return false;
2428  if (!pMsg) return false;
2429  if (pObj && !pObj->Status) return false;
2430  const char *szMsg = pMsg->GetCStr();
2431  if (!szMsg) return false;
2432  if (idDeco && !C4Id2Def(idDeco)) return false;
2433  if (iOwner.IsNil()) iOwner = NO_OWNER;
2434  // only one positioning flag per direction allowed
2435  uint32_t hpos = dwFlags & (C4GM_Left | C4GM_HCenter | C4GM_Right);
2436  uint32_t vpos = dwFlags & (C4GM_Top | C4GM_VCenter | C4GM_Bottom);
2437  if (((hpos | (hpos-1)) + 1)>>1 != hpos)
2438  {
2439  throw C4AulExecError("CustomMessage: Only one horizontal positioning flag allowed");
2440  }
2441  if (((vpos | (vpos-1)) + 1)>>1 != vpos)
2442  {
2443  throw C4AulExecError("CustomMessage: Only one vertical positioning flag allowed");
2444  }
2445  // message color
2446  if (!dwClr) dwClr = 0xffffffff;
2447  else dwClr = (dwClr&0xffffff) | (0xff000000u - uint32_t(dwClr|0xff000000)); // message internals use inverted alpha channel
2448  // message type
2449  int32_t iType;
2450  if (pObj)
2451  if (iOwner != NO_OWNER)
2452  iType = C4GM_TargetPlayer;
2453  else
2454  iType = C4GM_Target;
2455  else if (iOwner != NO_OWNER)
2456  iType = C4GM_GlobalPlayer;
2457  else
2458  iType = C4GM_Global;
2459  // remove speech?
2460  StdStrBuf sMsg;
2461  sMsg.Ref(szMsg);
2462  if (dwFlags & C4GM_DropSpeech) sMsg.SplitAtChar('$', nullptr);
2463  // create it!
2464  return ::Messages.New(iType,sMsg,pObj,iOwner,iOffX,iOffY,(uint32_t)dwClr, idDeco, pSrc, dwFlags, iHSize);
2465 }
2466 
2467 static int FnGuiOpen(C4PropList * _this, C4PropList *menu)
2468 {
2469  C4ScriptGuiWindow *window = new C4ScriptGuiWindow;
2470 
2471  ::Game.ScriptGuiRoot->AddChild(window);
2472 
2473  if (!window->CreateFromPropList(menu, true))
2474  {
2475  ::Game.ScriptGuiRoot->RemoveChild(window, false);
2476  return 0;
2477  }
2478 
2479  return window->GetID();
2480 }
2481 
2482 static bool FnGuiUpdateTag(C4PropList * _this, C4String *tag, int32_t guiID, int32_t childID, C4Object *target)
2483 {
2484  C4ScriptGuiWindow *window = ::Game.ScriptGuiRoot->GetChildByID(guiID);
2485  if (!window) return false;
2486  if (childID) // note: valid child IDs are always non-zero
2487  {
2488  C4ScriptGuiWindow *subwindow = window->GetSubWindow(childID, target);
2489  if (!subwindow) return false;
2490  subwindow->SetTag(tag);
2491  return true;
2492  }
2493  window->SetTag(tag);
2494  return true;
2495 }
2496 
2497 static bool FnGuiClose(C4PropList *_this, int32_t guiID, int32_t childID, C4Object *target)
2498 {
2499  C4ScriptGuiWindow *window = ::Game.ScriptGuiRoot->GetChildByID(guiID);
2500  if (!window) return false;
2501  if (childID) // note: valid child IDs are always non-zero
2502  {
2503  C4ScriptGuiWindow *subwindow = window->GetSubWindow(childID, target);
2504  if (!subwindow) return false;
2505  subwindow->Close();
2506  return true;
2507  }
2508  window->Close();
2509  return true;
2510 }
2511 
2512 static bool FnGuiUpdate(C4PropList *_this, C4PropList *update, int32_t guiID, int32_t childID, C4Object *target)
2513 {
2514  if (!update) return false;
2515  C4ScriptGuiWindow *window = ::Game.ScriptGuiRoot->GetChildByID(guiID);
2516  if (!window) return false;
2517  if (childID) // note: valid child IDs are always non-zero
2518  {
2519  C4ScriptGuiWindow *subwindow = window->GetSubWindow(childID, target);
2520  if (!subwindow) return false;
2521  subwindow->CreateFromPropList(update, false, true);
2522  return true;
2523  }
2524  window->CreateFromPropList(update, false, true);
2525  return true;
2526 }
2527 
2528 // undocumented!
2529 static bool FnPauseGame(C4PropList * _this, bool fToggle)
2530 {
2531  // not in replay (film)
2532  if (::Control.isReplay()) return true;
2533  // script method for halting game (for films)
2534  if (fToggle)
2535  Console.TogglePause();
2536  else
2537  Console.DoHalt();
2538  return true;
2539 }
2540 
2541 static bool FnSetNextMission(C4PropList * _this, C4String *szNextMission, C4String *szNextMissionText, C4String *szNextMissionDesc)
2542 {
2543  if (!szNextMission || !szNextMission->GetData().getLength())
2544  {
2545  // param empty: clear next mission
2548  }
2549  else
2550  {
2551  // set next mission, button and button desc if given
2552  Game.NextMission.Copy(szNextMission->GetData());
2553  if (szNextMissionText && szNextMissionText->GetCStr())
2554  {
2555  Game.NextMissionText.Copy(szNextMissionText->GetData());
2556  }
2557  else
2558  {
2559  Game.NextMissionText.Copy(LoadResStr("IDS_BTN_NEXTMISSION"));
2560  }
2561  if (szNextMissionDesc && szNextMissionDesc->GetCStr())
2562  {
2563  Game.NextMissionDesc.Copy(szNextMissionDesc->GetData());
2564  }
2565  else
2566  {
2567  Game.NextMissionDesc.Copy(LoadResStr("IDS_DESC_NEXTMISSION"));
2568  }
2569  }
2570  return true;
2571 }
2572 
2573 static long FnGetPlayerControlState(C4PropList * _this, long iPlr, long iControl, bool fMovedState)
2574 {
2575  // get control set to check
2576  C4PlayerControl *pCheckCtrl = nullptr;
2577  if (iPlr != NO_OWNER)
2578  {
2579  C4Player *pPlr = ::Players.Get(iPlr);
2580  if (pPlr)
2581  {
2582  pCheckCtrl = &(pPlr->Control);
2583  }
2584  }
2585  // invalid player or no controls
2586  if (!pCheckCtrl) return 0;
2587  // query control
2588  const C4PlayerControl::CSync::ControlDownState *pControlState = pCheckCtrl->GetControlDownState(iControl);
2589  // no state means not down
2590  if (!pControlState) return 0;
2591  // otherwise take either down-value or moved-value
2592  return fMovedState ? pControlState->MovedState.iStrength : pControlState->DownState.iStrength;
2593 }
2594 
2595 // undocumented!
2596 static bool FnSetPlayerControlEnabled(C4PropList * _this, long iplr, long ctrl, bool is_enabled)
2597 {
2598  // get control set to check
2599  C4PlayerControl *plrctrl = nullptr;
2600  if (iplr != NO_OWNER)
2601  {
2602  C4Player *plr = ::Players.Get(iplr);
2603  if (plr)
2604  {
2605  plrctrl = &(plr->Control);
2606  }
2607  }
2608  // invalid player or no controls
2609  if (!plrctrl) return false;
2610  // invalid control
2611  if (ctrl >= int32_t(Game.PlayerControlDefs.GetCount())) return false;
2612  // query
2613  return plrctrl->SetControlDisabled(ctrl, !is_enabled);
2614 }
2615 
2616 // undocumented!
2617 static bool FnGetPlayerControlEnabled(C4PropList * _this, long iplr, long ctrl)
2618 {
2619  // get control set to check
2620  C4PlayerControl *plrctrl = nullptr;
2621  if (iplr != NO_OWNER)
2622  {
2623  C4Player *plr = ::Players.Get(iplr);
2624  if (plr)
2625  {
2626  plrctrl = &(plr->Control);
2627  }
2628  }
2629  // invalid player or no controls
2630  if (!plrctrl) return false;
2631  return !plrctrl->IsControlDisabled(ctrl);
2632 }
2633 
2634 // undocumented!
2635 static C4String *FnGetPlayerControlAssignment(C4PropList * _this, long player, long control, bool human_readable, bool short_name)
2636 {
2637  // WARNING: As many functions returning strings, the result is not sync safe!
2638  // "" is returned for invalid controls to make the obvious if(GetPlayerControlAssignmentName(...)) not cause a sync loss
2639  // get desired assignment from parameters
2640  C4Player *plr = ::Players.Get(player);
2641  if (!plr) return nullptr; // invalid player
2642  if (!plr->ControlSet) return String(""); // player has no control (remote player)
2643  C4PlayerControlAssignment *assignment = plr->ControlSet->GetAssignmentByControl(control);
2644  if (!assignment) return String("");
2645  // get assignment as readable string
2646  return String(assignment->GetKeysAsString(human_readable, short_name).getData());
2647 }
2648 
2649 // strength: 0-1000, length: milliseconds
2650 static bool FnPlayRumble(C4PropList * _this, long player, long strength, long length)
2651 {
2652  // Check parameters.
2653  if (strength <= 0 || strength > 1000) return false;
2654  if (length <= 0) return false;
2655  // NO_OWNER: play rumble for all players (e.g. earthquakes)
2656  if (player == NO_OWNER)
2657  {
2658  for (C4Player *plr = ::Players.First; plr; plr=plr->Next)
2659  if (plr->Number != NO_OWNER) // can't happen, but would be a crash if it did...
2660  FnPlayRumble(_this, plr->Number, strength, length);
2661  return true;
2662  }
2663  C4Player *plr = ::Players.Get(player);
2664  if (!plr) return false;
2665  if (plr->pGamepad)
2666  plr->pGamepad->PlayRumble(strength / 1000.f, length);
2667  // We can't return whether the rumble was actually played.
2668  return true;
2669 }
2670 
2671 static bool FnStopRumble(C4PropList * _this, long player)
2672 {
2673  // NO_OWNER: stop rumble for all players
2674  // Not sure whether this makes sense to do - mainly provided for symmetry with PlayRumble().
2675  if (player == NO_OWNER)
2676  {
2677  for (C4Player *plr = ::Players.First; plr; plr=plr->Next)
2678  if (plr->Number != NO_OWNER) // can't happen, but would be a crash if it did...
2679  FnStopRumble(_this, plr->Number);
2680  return true;
2681  }
2682  C4Player *plr = ::Players.Get(player);
2683  if (!plr) return false;
2684  if (plr->pGamepad)
2685  plr->pGamepad->StopRumble();
2686  return true;
2687 }
2688 
2689 static int32_t FnGetStartupPlayerCount(C4PropList * _this)
2690 {
2691  // returns number of players when game was initially started
2693 }
2694 
2695 static int32_t FnGetStartupTeamCount(C4PropList * _this)
2696 {
2697  // returns number of non-empty teams when game was initially started
2699 }
2700 
2701 static bool FnGainScenarioAchievement(C4PropList * _this, C4String *achievement_name, Nillable<long> avalue, Nillable<long> player, C4String *for_scenario)
2702 {
2703  // safety
2704  if (!achievement_name || !achievement_name->GetData().getLength()) return false;
2705  // default parameter
2706  long value = avalue.IsNil() ? 1 : (long)avalue;
2707  // gain achievement
2708  bool result = true;
2709  if (!player.IsNil() && player != NO_OWNER)
2710  {
2711  C4Player *plr = ::Players.Get(player);
2712  if (!plr) return false;
2713  result = plr->GainScenarioAchievement(achievement_name->GetCStr(), value, for_scenario ? for_scenario->GetCStr() : nullptr);
2714  }
2715  else
2716  {
2717  for (C4Player *plr = ::Players.First; plr; plr = plr->Next)
2718  if (!plr->GainScenarioAchievement(achievement_name->GetCStr(), value, for_scenario ? for_scenario->GetCStr() : nullptr))
2719  result = false;
2720  }
2721  return result;
2722 }
2723 
2724 static long FnGetPXSCount(C4PropList * _this, Nillable<long> iMaterial, Nillable<long> iX0, Nillable<long> iY0, Nillable<long> iWdt, Nillable<long> iHgt)
2725 {
2726  if (iX0.IsNil())
2727  {
2728  // Search everywhere
2729  // All materials everywhere
2730  if (iMaterial.IsNil() || iMaterial == MNone) return ::PXS.GetCount();
2731  // Specific material everywhere
2732  return ::PXS.GetCount(iMaterial);
2733  }
2734  else
2735  {
2736  // Material in area; offset by caller
2737  int32_t x = iX0, y = iY0;
2738  if (Object(_this)) { x += Object(_this)->GetX(); y += Object(_this)->GetY(); }
2739  return ::PXS.GetCount(iMaterial.IsNil() ? MNone : static_cast<int32_t>(iMaterial), x, y, iWdt, iHgt);
2740  }
2741 }
2742 
2743 static C4String *FnGetTranslatedString(C4PropList * _this, const C4Value & string_data)
2744 {
2745  // Resolve proplists containing localized strings to the current localization
2746  return ::Game.GetTranslatedString(string_data, nullptr, false);
2747 }
2748 
2751 
2753 {
2754  // add all def constants (all Int)
2755  for (C4ScriptConstDef *pCDef = &C4ScriptGameConstMap[0]; pCDef->Identifier; pCDef++)
2756  {
2757  assert(pCDef->ValType == C4V_Int); // only int supported currently
2758  pEngine->RegisterGlobalConstant(pCDef->Identifier, C4VInt(pCDef->Data));
2759  }
2760  C4PropListStatic * p = pEngine->GetPropList();
2761  // add all def script funcs
2762  for (C4ScriptFnDef *pDef = &C4ScriptGameFnMap[0]; pDef->Identifier; pDef++)
2763  new C4AulDefFunc(p, pDef);
2764 #define F(f) ::AddFunc(p, #f, Fn##f)
2765  F(GetX);
2766  F(GetY);
2767  F(GetDefinition);
2768  F(GetDefinitionGroupPath);
2769  F(GetPlayerName);
2770  F(GetPlayerType);
2771  F(GetPlayerColor);
2772  F(GetPlrClonkSkin);
2773  F(CreateObject);
2774  F(CreateObjectAbove);
2775  F(CreateConstruction);
2776  F(FindConstructionSite);
2777  F(CheckConstructionSite);
2778  F(Sound);
2779  F(SoundAt);
2780  F(ChangeSoundModifier);
2781  F(SetGlobalSoundModifier);
2782  F(Music);
2783  F(MusicLevel);
2784  F(SetPlayList);
2785  F(SetPlrView);
2786  F(SetPlrKnowledge);
2787  F(GetPlrViewMode);
2788  F(ResetCursorView);
2789  F(GetPlrView);
2790  F(GetWealth);
2791  F(SetWealth);
2792  F(DoPlayerScore);
2793  F(GetPlayerScore);
2794  F(GetPlayerScoreGain);
2795  F(GetWind);
2796  F(SetWind);
2797  F(GetTemperature);
2798  F(SetTemperature);
2799  F(ShakeFree);
2800  F(DigFree);
2801  F(DigFreeRect);
2802  F(ClearFreeRect);
2803  F(Hostile);
2804  F(SetHostility);
2805  F(PlaceVegetation);
2806  F(PlaceAnimal);
2807  F(GameOver);
2808  F(GetHiRank);
2809  F(GetCrew);
2810  F(GetCrewCount);
2811  F(GetPlayerCount);
2812  F(GetPlayerByIndex);
2813  F(EliminatePlayer);
2814  F(SurrenderPlayer);
2815  F(GetLeagueScore);
2816  F(SetLeaguePerformance);
2817  F(SetLeagueProgressData);
2818  F(GetLeagueProgressData);
2819  F(CreateScriptPlayer);
2820  F(GetCursor);
2821  F(GetViewCursor);
2822  F(SetCursor);
2823  F(SetViewCursor);
2824  F(GetMaterial);
2825  F(GetBackMaterial);
2826  F(GetTexture);
2827  F(GetBackTexture);
2828  F(GetAverageTextureColor);
2829  F(GetMaterialCount);
2830  F(GBackSolid);
2831  F(GBackSemiSolid);
2832  F(GBackLiquid);
2833  F(GBackSky);
2834  F(Material);
2835  F(BlastFree);
2836  F(InsertMaterial);
2837  F(CanInsertMaterial);
2838  F(LandscapeWidth);
2839  F(LandscapeHeight);
2840  F(SetAmbientBrightness);
2841  F(GetAmbientBrightness);
2842  F(SetSeason);
2843  F(GetSeason);
2844  F(SetClimate);
2845  F(GetClimate);
2846  F(SetPlayerZoomByViewRange);
2847  F(GetPlayerZoomLimits);
2848  F(SetPlayerZoom);
2849  F(SetPlayerViewLock);
2850  F(DoBaseMaterial);
2851  F(DoBaseProduction);
2852  F(GainMissionAccess);
2853  F(IsNetwork);
2854  F(IsEditor);
2855  F(GetLeague);
2856  ::AddFunc(p, "TestMessageBoard", FnTestMessageBoard, false);
2857  ::AddFunc(p, "CallMessageBoard", FnCallMessageBoard, false);
2858  ::AddFunc(p, "AbortMessageBoard", FnAbortMessageBoard, false);
2859  F(SetFoW);
2860  F(SetMaxPlayer);
2861  F(Object);
2862  F(GetTime);
2863  F(GetMissionAccess);
2864  F(MaterialName);
2865  F(DrawMap);
2866  F(DrawDefMap);
2867  F(CreateParticle);
2868  F(ClearParticles);
2869  F(SetSky);
2870  F(SetSkyAdjust);
2871  F(SetMatAdjust);
2872  F(GetSkyAdjust);
2873  F(GetMatAdjust);
2874  F(SetSkyParallax);
2875  F(ReloadDef);
2876  F(ReloadParticle);
2877  F(SetGamma);
2878  F(ResetGamma);
2879  F(AddFragmentShader);
2880  F(RemoveShader);
2881  F(FrameCounter);
2882  F(DrawMaterialQuad);
2883  F(SetFilmView);
2884  F(AddMsgBoardCmd);
2885  ::AddFunc(p, "SetGameSpeed", FnSetGameSpeed, false);
2886  ::AddFunc(p, "DrawMatChunks", FnDrawMatChunks, false);
2887  F(GetPathLength);
2888  F(SetTextureIndex);
2889  F(RemoveUnusedTexMapEntries);
2890  F(SimFlight);
2891  F(LoadScenarioSection);
2892  F(SetViewOffset);
2893  ::AddFunc(p, "SetPreSend", FnSetPreSend, false);
2894  F(GetPlayerID);
2895  F(GetPlayerTeam);
2896  F(SetPlayerTeam);
2897  F(GetScriptPlayerExtraID);
2898  F(GetTeamConfig);
2899  F(GetTeamName);
2900  F(GetTeamColor);
2901  F(GetTeamByIndex);
2902  F(GetTeamCount);
2903  ::AddFunc(p, "InitScenarioPlayer", FnInitScenarioPlayer, false);
2904  F(SetScoreboardData);
2905  ::AddFunc(p, "GetScoreboardString", FnGetScoreboardString, false);
2906  ::AddFunc(p, "GetScoreboardData", FnGetScoreboardData, false);
2907  F(DoScoreboardShow);
2908  F(SortScoreboard);
2909  F(AddEvaluationData);
2910  F(HideSettlementScoreInEvaluation);
2911  F(ExtractMaterialAmount);
2912  F(CustomMessage);
2913  F(GuiOpen);
2914  F(GuiUpdateTag);
2915  F(GuiClose);
2916  F(GuiUpdate);
2917  ::AddFunc(p, "PauseGame", FnPauseGame, false);
2918  F(PathFree);
2919  F(PathFree2);
2920  F(SetNextMission);
2921  F(GetPlayerControlState);
2922  F(SetPlayerControlEnabled);
2923  F(GetPlayerControlEnabled);
2924  F(GetPlayerControlAssignment);
2925  F(PlayRumble);
2926  F(StopRumble);
2927  F(GetStartupPlayerCount);
2928  F(GetStartupTeamCount);
2929  F(EditCursor);
2930  F(GainScenarioAchievement);
2931  F(GetPXSCount);
2932  F(GetPlrKnowledge);
2933  F(GetBaseMaterial);
2934  F(GetBaseProduction);
2935  F(GetDefCoreVal);
2936  F(GetObjectVal);
2937  F(GetObjectInfoCoreVal);
2938  F(GetScenarioVal);
2939  F(GetPlayerVal);
2940  F(GetPlayerInfoCoreVal);
2941  F(GetMaterialVal);
2942  F(SetPlrExtraData);
2943  F(GetPlrExtraData);
2944  F(PV_Linear);
2945  F(PV_Random);
2946  F(PV_Direction);
2947  F(PV_Step);
2948  F(PV_Speed);
2949  F(PV_Wind);
2950  F(PV_Gravity);
2951  // F(PV_KeyFrames); added below
2952  F(PV_Sin);
2953  F(PV_Cos);
2954  F(PC_Die);
2955  F(PC_Bounce);
2956  F(PC_Stop);
2957  F(IncinerateLandscape);
2958  F(GetGravity);
2959  F(SetGravity);
2960  F(GetTranslatedString);
2961 #undef F
2962 }
2963 
2964 C4ScriptConstDef C4ScriptGameConstMap[]=
2965 {
2966  { "NO_OWNER" ,C4V_Int, NO_OWNER }, // invalid player number
2967 
2968  // material density
2969  { "C4M_Vehicle" ,C4V_Int, C4M_Vehicle },
2970  { "C4M_Solid" ,C4V_Int, C4M_Solid },
2971  { "C4M_SemiSolid" ,C4V_Int, C4M_SemiSolid },
2972  { "C4M_Liquid" ,C4V_Int, C4M_Liquid },
2973  { "C4M_Background" ,C4V_Int, C4M_Background },
2974 
2975  // scoreboard
2976  { "SBRD_Caption" ,C4V_Int, C4Scoreboard::TitleKey }, // used to set row/coloumn headers
2977 
2978  // teams - constants for GetTeamConfig
2979  { "TEAM_Custom" ,C4V_Int, C4TeamList::TEAM_Custom },
2980  { "TEAM_Active" ,C4V_Int, C4TeamList::TEAM_Active },
2981  { "TEAM_AllowHostilityChange" ,C4V_Int, C4TeamList::TEAM_AllowHostilityChange },
2982  { "TEAM_Dist" ,C4V_Int, C4TeamList::TEAM_Dist },
2983  { "TEAM_AllowTeamSwitch" ,C4V_Int, C4TeamList::TEAM_AllowTeamSwitch },
2984  { "TEAM_AutoGenerateTeams" ,C4V_Int, C4TeamList::TEAM_AutoGenerateTeams },
2985  { "TEAM_TeamColors" ,C4V_Int, C4TeamList::TEAM_TeamColors },
2986 
2987  { "C4FO_Not" ,C4V_Int, C4FO_Not },
2988  { "C4FO_And" ,C4V_Int, C4FO_And },
2989  { "C4FO_Or" ,C4V_Int, C4FO_Or },
2990  { "C4FO_Exclude" ,C4V_Int, C4FO_Exclude },
2991  { "C4FO_InRect" ,C4V_Int, C4FO_InRect },
2992  { "C4FO_AtPoint" ,C4V_Int, C4FO_AtPoint },
2993  { "C4FO_AtRect" ,C4V_Int, C4FO_AtRect },
2994  { "C4FO_OnLine" ,C4V_Int, C4FO_OnLine },
2995  { "C4FO_Distance" ,C4V_Int, C4FO_Distance },
2996  { "C4FO_ID" ,C4V_Int, C4FO_ID },
2997  { "C4FO_OCF" ,C4V_Int, C4FO_OCF },
2998  { "C4FO_Category" ,C4V_Int, C4FO_Category },
2999  { "C4FO_Action" ,C4V_Int, C4FO_Action },
3000  { "C4FO_ActionTarget" ,C4V_Int, C4FO_ActionTarget },
3001  { "C4FO_Procedure" ,C4V_Int, C4FO_Procedure },
3002  { "C4FO_Container" ,C4V_Int, C4FO_Container },
3003  { "C4FO_AnyContainer" ,C4V_Int, C4FO_AnyContainer },
3004  { "C4FO_Owner" ,C4V_Int, C4FO_Owner },
3005  { "C4FO_Controller" ,C4V_Int, C4FO_Controller },
3006  { "C4FO_Func" ,C4V_Int, C4FO_Func },
3007  { "C4FO_Layer" ,C4V_Int, C4FO_Layer },
3008  { "C4FO_InArray" ,C4V_Int, C4FO_InArray },
3009  { "C4FO_Property" ,C4V_Int, C4FO_Property },
3010  { "C4FO_AnyLayer" ,C4V_Int, C4FO_AnyLayer },
3011  { "C4FO_Cone" ,C4V_Int, C4FO_Cone },
3012 
3013  { "MD_DragSource" ,C4V_Int, C4MC_MD_DragSource },
3014  { "MD_DropTarget" ,C4V_Int, C4MC_MD_DropTarget },
3015  { "MD_NoClick" ,C4V_Int, C4MC_MD_NoClick },
3016 
3017  { "C4SO_Reverse" ,C4V_Int, C4SO_Reverse },
3018  { "C4SO_Multiple" ,C4V_Int, C4SO_Multiple },
3019  { "C4SO_Distance" ,C4V_Int, C4SO_Distance },
3020  { "C4SO_Random" ,C4V_Int, C4SO_Random },
3021  { "C4SO_Speed" ,C4V_Int, C4SO_Speed },
3022  { "C4SO_Mass" ,C4V_Int, C4SO_Mass },
3023  { "C4SO_Value" ,C4V_Int, C4SO_Value },
3024  { "C4SO_Func" ,C4V_Int, C4SO_Func },
3025 
3026  { "C4SECT_SaveLandscape" ,C4V_Int, C4S_SAVE_LANDSCAPE },
3027  { "C4SECT_SaveObjects" ,C4V_Int, C4S_SAVE_OBJECTS },
3028  { "C4SECT_KeepEffects" ,C4V_Int, C4S_KEEP_EFFECTS },
3029  { "C4SECT_ReinitScenario" ,C4V_Int, C4S_REINIT_SCENARIO },
3030 
3031  { "TEAMID_New" ,C4V_Int, TEAMID_New },
3032 
3033  { "MSG_NoLinebreak" ,C4V_Int, C4GM_NoBreak },
3034  { "MSG_Bottom" ,C4V_Int, C4GM_Bottom },
3035  { "MSG_Multiple" ,C4V_Int, C4GM_Multiple },
3036  { "MSG_Top" ,C4V_Int, C4GM_Top },
3037  { "MSG_Left" ,C4V_Int, C4GM_Left },
3038  { "MSG_Right" ,C4V_Int, C4GM_Right },
3039  { "MSG_HCenter" ,C4V_Int, C4GM_HCenter },
3040  { "MSG_VCenter" ,C4V_Int, C4GM_VCenter },
3041  { "MSG_DropSpeech" ,C4V_Int, C4GM_DropSpeech },
3042  { "MSG_WidthRel" ,C4V_Int, C4GM_WidthRel },
3043  { "MSG_XRel" ,C4V_Int, C4GM_XRel },
3044  { "MSG_YRel" ,C4V_Int, C4GM_YRel },
3045  { "MSG_Zoom" ,C4V_Int, C4GM_Zoom },
3046 
3047  { "C4PT_User" ,C4V_Int, C4PT_User },
3048  { "C4PT_Script" ,C4V_Int, C4PT_Script },
3049 
3050  { "CSPF_FixedAttributes" ,C4V_Int, CSPF_FixedAttributes },
3051  { "CSPF_NoScenarioInit" ,C4V_Int, CSPF_NoScenarioInit },
3052  { "CSPF_NoEliminationCheck" ,C4V_Int, CSPF_NoEliminationCheck },
3053  { "CSPF_Invisible" ,C4V_Int, CSPF_Invisible },
3054  { "CSPF_NoScenarioSave" ,C4V_Int, CSPF_NoScenarioSave },
3055 
3056  { "DMQ_Sky" ,C4V_Int, DMQ_Sky },
3057  { "DMQ_Sub" ,C4V_Int, DMQ_Sub },
3058  { "DMQ_Bridge" ,C4V_Int, DMQ_Bridge },
3059 
3060  { "PLRZOOM_Direct" ,C4V_Int, PLRZOOM_Direct },
3061  { "PLRZOOM_NoIncrease" ,C4V_Int, PLRZOOM_NoIncrease },
3062  { "PLRZOOM_NoDecrease" ,C4V_Int, PLRZOOM_NoDecrease },
3063  { "PLRZOOM_LimitMin" ,C4V_Int, PLRZOOM_LimitMin },
3064  { "PLRZOOM_LimitMax" ,C4V_Int, PLRZOOM_LimitMax },
3065  { "PLRZOOM_Set" ,C4V_Int, PLRZOOM_Set },
3066 
3067  { "ATTACH_Front" ,C4V_Int, C4ATTACH_Front },
3068  { "ATTACH_Back" ,C4V_Int, C4ATTACH_Back },
3069  { "ATTACH_MoveRelative" ,C4V_Int, C4ATTACH_MoveRelative },
3070 
3071  // sound modifier type
3072  { "C4SMT_Reverb" ,C4V_Int, C4SoundModifier::C4SMT_Reverb },
3073  { "C4SMT_Echo" ,C4V_Int, C4SoundModifier::C4SMT_Echo },
3074  { "C4SMT_Equalizer" ,C4V_Int, C4SoundModifier::C4SMT_Equalizer },
3075 
3076  { "GUI_SetTag" ,C4V_Int, C4ScriptGuiWindowActionID::SetTag },
3077  { "GUI_Call" ,C4V_Int, C4ScriptGuiWindowActionID::Call },
3078  { "GUI_GridLayout" ,C4V_Int, C4ScriptGuiWindowStyleFlag::GridLayout },
3079  { "GUI_TightGridLayout" ,C4V_Int, C4ScriptGuiWindowStyleFlag::TightGridLayout },
3080  { "GUI_VerticalLayout" ,C4V_Int, C4ScriptGuiWindowStyleFlag::VerticalLayout },
3081  { "GUI_TextVCenter" ,C4V_Int, C4ScriptGuiWindowStyleFlag::TextVCenter },
3082  { "GUI_TextHCenter" ,C4V_Int, C4ScriptGuiWindowStyleFlag::TextHCenter },
3083  { "GUI_TextRight" ,C4V_Int, C4ScriptGuiWindowStyleFlag::TextRight },
3084  { "GUI_TextBottom" ,C4V_Int, C4ScriptGuiWindowStyleFlag::TextBottom },
3085  { "GUI_TextTop" ,C4V_Int, C4ScriptGuiWindowStyleFlag::None }, // note that top and left are considered default
3086  { "GUI_TextLeft" ,C4V_Int, C4ScriptGuiWindowStyleFlag::None }, // they are only included for completeness
3087  { "GUI_FitChildren" ,C4V_Int, C4ScriptGuiWindowStyleFlag::FitChildren },
3088  { "GUI_Multiple" ,C4V_Int, C4ScriptGuiWindowStyleFlag::Multiple },
3089  { "GUI_IgnoreMouse" ,C4V_Int, C4ScriptGuiWindowStyleFlag::IgnoreMouse },
3090  { "GUI_NoCrop" ,C4V_Int, C4ScriptGuiWindowStyleFlag::NoCrop },
3091 
3092  // control states
3093  { "CONS_Down" ,C4V_Int, C4PlayerControl::CONS_Down },
3094  { "CONS_Up" ,C4V_Int, C4PlayerControl::CONS_Up },
3095  { "CONS_Moved" ,C4V_Int, C4PlayerControl::CONS_Moved },
3096 
3097  { "PLRCON_MaxStrength" ,C4V_Int, C4GamePadControl::MaxStrength },
3098 
3099  { nullptr, C4V_Nil, 0}
3100 };
3101 
3102 C4ScriptFnDef C4ScriptGameFnMap[]=
3103 {
3104  { "FindObject", true, C4V_Object, { C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnFindObject },
3105  { "FindObjects", true, C4V_Array, { C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnFindObjects },
3106  { "ObjectCount", true, C4V_Int, { C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnObjectCount },
3107  { "GameCallEx", true, C4V_Any, { C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnGameCallEx },
3108  { "PlayerMessage", true, C4V_Int, { C4V_Int ,C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnPlayerMessage },
3109  { "Message", true, C4V_Bool, { C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnMessage },
3110  { "AddMessage", true, C4V_Bool, { C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnAddMessage },
3111  { "PV_KeyFrames", true, C4V_Array, { C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnPV_KeyFrames },
3112 
3113  { nullptr, false, C4V_Nil, { C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil}, nullptr }
3114 };
const char * getData() const
Definition: StdBuf.h:442
C4SoundSystem SoundSystem
Definition: C4Application.h:42
bool DoGameOver()
Definition: C4Game.cpp:3095
void DWord(uint32_t &rInt) override
C4EditCursor EditCursor
Definition: C4Console.h:90
C4Def * ID2Def(C4ID id)
int32_t GetY() const
Definition: C4Object.h:287
class C4PlayerInfo * GetInfo()
Definition: C4Player.cpp:1551
void SetFoW(bool fEnable)
Definition: C4Player.cpp:723
int32_t GetIDCount(C4ID c_id, int32_t iZeroDefVal=0) const
Definition: stub-handle.cpp:67
void Denumerate()
Definition: C4Value.cpp:281
StdStrBuf GetData() const
Definition: C4StringTable.h:50
static C4FindObject * CreateByValue(const C4Value &Data, C4SortObject **ppSortObj=nullptr, const C4Object *context=nullptr, bool *has_layer_check=nullptr)
void RegisterGlobalConstant(const char *szName, const C4Value &rValue)
bool operator()(int32_t iX, int32_t iY, C4Object *TransferTarget)
C4Viewport * GetFirstViewport()
Definition: C4Viewport.h:156
int32_t GetID() const
Definition: C4Teams.h:66
C4ID id
Definition: C4Def.h:101
bool GetSection(size_t idx, StdStrBuf *psOutSection, char cSeparator=';') const
Definition: StdBuf.cpp:369
void SetMusicBreakMax(int32_t val)
C4Object * CreateObjectConstruction(C4PropList *type, C4Object *pCreator, int32_t owner, int32_t ctx=0, int32_t bty=0, int32_t con=1, bool terrain=false)
Definition: C4Game.cpp:1102
void SetItem(int32_t iElemNr, const C4Value &Value)
const int32_t C4GM_Multiple
Definition: C4GameMessage.h:36
C4Config Config
Definition: C4Config.cpp:833
const int32_t C4M_Vehicle
Definition: C4Constants.h:171
void SetLeaguePerformance(int32_t iNewPerf, int32_t idPlayer=0)
DWORD GetModulation() const
#define PSF_OnTeamSwitch
Definition: C4GameScript.h:145
void SetTemperature(int32_t iTemperature)
Definition: C4Weather.cpp:120
SumPathLength(PathInfo *info)
void GameMsgObjectPlayer(const char *szText, C4Object *pTarget, int32_t iPlayer)
bool SimFlight(C4Real &x, C4Real &y, C4Real &xdir, C4Real &ydir, int32_t iDensityMin, int32_t iDensityMax, int32_t &iIter)
Definition: C4Movement.cpp:610
void SetMusicBreakMin(int32_t val)
int32_t Team
Definition: C4Player.h:88
C4ObjectPtr Cursor
Definition: C4Player.h:130
DWORD GetModulation(bool fBackClr)
Definition: C4Sky.h:43
StdCopyStrBuf NextMission
Definition: C4Game.h:146
C4Console Console
Definition: C4Globals.cpp:45
C4PropListStatic * GetPropList()
Definition: C4Aul.h:151
bool Incinerate(int32_t x, int32_t y, int32_t cause_player)
C4String * getStr() const
Definition: C4Value.h:117
bool HasMessageBoardQuery()
Definition: C4Player.cpp:1697
int32_t ViewMode
Definition: C4Player.h:105
bool isCtrlHost() const
Definition: C4GameControl.h:99
bool GetProperty(C4PropertyName k, C4Value *pResult) const
Definition: C4PropList.h:101
C4Game Game
Definition: C4Globals.cpp:52
char MissionAccess[CFG_MaxString+1]
Definition: C4Config.h:45
bool IsTeamColors() const
Definition: C4Teams.h:169
int32_t Number
Definition: C4Player.h:86
C4Def * GetDef(int32_t Index)
void SetMaxZoom(C4Real zoom, bool no_increase, bool no_decrease)
Definition: C4Player.cpp:1829
C4GameScriptHost GameScript
C4String * String(const char *str)
Definition: C4AulDefFunc.h:30
C4AulScriptEngine ScriptEngine
Definition: C4Globals.cpp:43
C4Scenario C4S
Definition: C4Game.h:74
bool SplitAtChar(char cSplit, StdStrBuf *psSplit)
Definition: StdBuf.h:619
void Clear()
Definition: StdBuf.h:466
int32_t DigFree(int32_t tx, int32_t ty, int32_t rad, C4Object *by_object=nullptr, bool no_dig2objects=false, bool no_instability_check=false)
C4ConfigGeneral General
Definition: C4Config.h:251
C4ParticleSystem Particles
Definition: C4Teams.h:30
bool SetTextureIndex(const char *szMatTex, BYTE iNewIndex, bool fInsert)
void SetTeam(int32_t idToTeam)
Definition: C4PlayerInfo.h:120
uint32_t GetColor() const
Definition: C4Teams.h:70
bool SCopySegment(const char *szString, int iSegment, char *sTarget, char cSeparator, int iMaxL, bool fSkipWhitespace)
Definition: Standard.cpp:273
C4PlayerControlAssignment * GetAssignmentByControl(int32_t control)
void EnsureDefinitionListInitialized()
Definition: C4ConsoleGUI.h:115
const int32_t C4GM_DropSpeech
Definition: C4GameMessage.h:42
bool IsAutoGenerateTeams() const
Definition: C4Teams.h:172
const int32_t C4GM_Top
Definition: C4GameMessage.h:37
void Byte(uint8_t &rByte) override
const int32_t C4GM_YRel
Definition: C4GameMessage.h:45
#define C4S_REINIT_SCENARIO
Definition: C4Scenario.h:51
bool IsChosingTeam() const
Definition: C4Player.h:202
void Eliminate()
Definition: C4Player.cpp:1472
void NameEnd(bool fBreak=false) override
C4Material * Map
Definition: C4Material.h:169
C4Object * FnPlaceVegetation(C4PropList *_this, C4PropList *Def, long iX, long iY, long iWdt, long iHgt, long iGrowth, C4PropList *shape)
const char * GetCStr() const
Definition: C4StringTable.h:49
C4String * RegString(StdStrBuf String)
int32_t ParallaxMode
Definition: C4Sky.h:59
bool TogglePause()
Definition: C4Console.cpp:617
int32_t PrefClonkSkin
Definition: C4InfoCore.h:100
C4Value C4VInt(int32_t i)
Definition: C4Value.h:242
void DoDlgShow(int32_t iChange, bool fUserToggle)
double GetBrightness() const
Definition: C4FoWAmbient.h:56
StdCopyStrBuf League
C4Team * GetGenerateTeamByID(int32_t iID)
Definition: C4Teams.cpp:390
void SetProperty(C4PropertyName k, const C4Value &to)
Definition: C4PropList.h:120
static const int32_t MaxStrength
Definition: C4GamePadCon.h:48
bool ScenarioAndTeamInit(int32_t idTeam)
Definition: C4Player.cpp:118
#define C4S_SAVE_LANDSCAPE
Definition: C4Scenario.h:48
bool Find(int32_t iFromX, int32_t iFromY, int32_t iToX, int32_t iToY, SetWaypointFn fnSetWaypoint)
class C4ParticleList * BackParticles
Definition: C4Object.h:158
int32_t ZoomLimitMinHgt
Definition: C4Player.h:112
uint32_t GetAverageColor() const
Definition: C4Texture.h:38
bool HasFoW() const
int32_t DigFreeRect(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, C4Object *by_object=nullptr, bool no_dig2objects=false, bool no_instability_check=false)
class C4FoW * GetFoW()
void ProcessString(char **pszString, bool fIsID) override
C4Real C4REAL100(int x)
Definition: C4Real.h:267
uint8_t BYTE
C4Player * First
Definition: C4PlayerList.h:31
const int32_t C4GM_XRel
Definition: C4GameMessage.h:44
bool SetModulation(DWORD dwWithClr)
void DoHalt()
Definition: C4Console.cpp:100
bool SetAsScriptPlayer(const char *szName, uint32_t dwColor, uint32_t dwFlags, C4ID idExtra)
int SetPlayList(const char *szPlayList, bool fForceSwitch=false, int fadetime_ms=0, double max_resume_time=0.0)
C4TextureMap TextureMap
Definition: C4Texture.cpp:576
C4MessageInput MessageInput
const CSync::ControlDownState * GetControlDownState(int32_t iControl) const
bool IsMultiTeams() const
Definition: C4Teams.h:162
void SetBrightness(double brightness)
Definition: C4FoWAmbient.h:55
void StopSoundEffect(const char *szSndName, C4Object *pObj)
bool SIsModule(const char *szList, const char *szString, int *ipIndex, bool fCaseSensitive)
Definition: Standard.cpp:541
C4Viewport * GetViewport(int32_t iPlayer, C4Viewport *pPrev=nullptr)
C4PlayerControl Control
Definition: C4Player.h:129
C4Scoreboard Scoreboard
Definition: C4Game.h:94
bool LoadScenarioSection(const char *szSection, DWORD dwFlags)
Definition: C4Game.cpp:3467
int32_t GetMatCount(int material) const
void SetTag(C4String *tag)
C4Team * GetTeamByID(int32_t iID) const
Definition: C4Teams.cpp:383
bool InsertMaterial(int32_t mat, int32_t *tx, int32_t *ty, int32_t vx=0, int32_t vy=0, bool query_only=false)
int GetCount() const
C4SoundModifier * Get(class C4PropList *props, bool create_if_not_found)
void SetCursor(C4Object *pObj, bool fSelectArrow)
Definition: C4Player.cpp:1348
const C4TexMapEntry * GetEntry(int32_t iIndex) const
Definition: C4Texture.h:85
Definition: C4Texture.h:48
void SetLevel(int iLevel)
int32_t Wind
Definition: C4Weather.h:31
void Clear()
Definition: C4Sky.cpp:159
C4GraphicsResource GraphicsResource
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
C4ObjectPtr Layer
Definition: C4Object.h:136
C4GameParameters & Parameters
Definition: C4Game.h:67
void SetWind(int32_t iWind)
Definition: C4Weather.cpp:114
C4Value C4VObj(C4Object *pObj)
Definition: C4Value.cpp:88
const int32_t C4MC_MD_NoClick
int32_t ZoomLimitMaxWdt
Definition: C4Player.h:112
const int32_t C4MC_MD_DropTarget
const int32_t C4GM_TargetPlayer
Definition: C4GameMessage.h:32
const int32_t C4GM_NoBreak
Definition: C4GameMessage.h:34
C4PlayerInfo * GetPlayerInfoByID(int32_t id) const
C4TeamList & Teams
Definition: C4Game.h:70
C4Real x
Definition: C4Sky.h:56
void SetMusicBreakChance(int32_t val)
virtual C4Object * GetObject()
Definition: C4PropList.cpp:667
C4ObjectInfo * Info
Definition: C4Object.h:145
C4ValueMapData ExtraData
Definition: C4InfoCore.h:93
std::shared_ptr< class C4GamePadOpener > pGamepad
Definition: C4Player.h:132
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
void Character(char &rChar) override
const int32_t C4GM_Bottom
Definition: C4GameMessage.h:35
Definition: C4Real.h:58
void ProcessInt(int32_t &rInt) override
virtual C4Def const * GetDef() const
Definition: C4PropList.cpp:685
void SetSort(C4SortObject *pToSort)
const int32_t FullCon
Definition: C4Constants.h:181
char * getMData()
Definition: StdBuf.h:443
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
Definition: StdAdaptors.h:92
StdCopyStrBuf NextMissionDesc
Definition: C4Game.h:146
int32_t Distance(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2)
Definition: Standard.cpp:25
void AddCommand(const char *strCommand, const char *strScript)
uint32_t ColorDw
Definition: C4Player.h:89
C4SoundInstance * StartSoundEffect(const char *szSndName, bool fLoop, int32_t iVolume, C4Object *pObj, int32_t iCustomFalloffDistance, int32_t iPitch, C4SoundModifier *modifier)
void SetZoom(C4Real zoom, bool direct, bool no_increase, bool no_decrease)
Definition: C4Player.cpp:1817
const char * GetCellString(int32_t iColKey, int32_t iRowKey)
int32_t AddName(const char *pnName)
Definition: C4ValueMap.cpp:429
void ProcessBool(bool &rBool) override
void CallMessageBoard(C4Object *pForObj, const StdStrBuf &sQueryString, bool fUppercase)
Definition: C4Player.cpp:1663
#define PSF_RejectTeamSwitch
Definition: C4GameScript.h:131
int32_t Wdt
Definition: C4Rect.h:30
int32_t GetClimate()
Definition: C4Weather.cpp:143
const DWORD C4D_Load_RX
Definition: C4Def.h:91
void InitGameFunctionMap(C4AulScriptEngine *pEngine)
void Raw(void *pData, size_t iSize, RawCompileType eType=RCT_Escaped) override
void SoundUpdate(C4SoundInstance *pInst, int32_t iLevel, int32_t iPitch)
C4Player * Get(int iPlayer) const
C4ValueArray * FindMany(const C4ObjectList &Objs)
#define C4AUL_MAX_Par
Definition: C4AulFunc.h:26
int32_t FrameCounter
Definition: C4Game.h:128
const int32_t C4GM_Zoom
Definition: C4GameMessage.h:46
C4Real y
Definition: C4Sky.h:56
class C4PlayerControlAssignmentSet * ControlSet
Definition: C4Player.h:90
bool isNetwork() const
Definition: C4GameControl.h:97
const int32_t MNone
Definition: C4Constants.h:177
void Denumerate(C4ValueNumbers *)
Definition: C4Value.cpp:251
bool DebugLogF(const char *strMessage...)
Definition: C4Log.cpp:278
void String(char **pszString, RawCompileType eType) override
bool IsTeamSwitchAllowed() const
Definition: C4Teams.h:165
C4Shape Shape
Definition: C4Def.h:104
C4SoundModifierList Modifiers
Definition: C4SoundSystem.h:54
#define F(f)
bool IsNil() const
Definition: C4AulDefFunc.h:57
C4Def * Def
Definition: C4Object.h:143
bool CrewDisabled
Definition: C4Object.h:163
C4Player * GetByIndex(int iIndex) const
char Name[C4M_MaxName+1]
Definition: C4Material.h:89
bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt, int32_t hrange)
bool Append(int32_t iType, const char *szText, C4Object *pTarget, int32_t iPlayer, int32_t iX, int32_t iY, uint32_t bCol, bool fNoDuplicates=false)
C4V_Type GetType() const
Definition: C4Value.h:161
C4Object * GetHiRankActiveCrew()
Definition: C4Player.cpp:886
C4StringTable Strings
Definition: C4Globals.cpp:42
int iCnt
Definition: TstC4NetIO.cpp:32
#define PSF_OnHostilityChange
Definition: C4GameScript.h:144
int32_t GetEffectiveMatCount(int material) const
C4Value C4VPropList(C4PropList *p)
Definition: C4Value.h:245
C4IDList Knowledge
Definition: C4Player.h:127
void SetZoomByViewRange(int32_t range_wdt, int32_t range_hgt, bool direct, bool no_increase, bool no_decrease)
Definition: C4Player.cpp:1796
void ShakeFree(int32_t tx, int32_t ty, int32_t rad)
C4GameControl Control
const int32_t C4GM_Right
Definition: C4GameMessage.h:39
const char * GetTextureName() const
Definition: C4Texture.h:61
C4Landscape Landscape
void ProcessString(std::string &str, bool fIsID) override
void SetViewMode(int32_t iMode, C4Object *pTarget=nullptr, bool immediate_position=false)
Definition: C4Player.cpp:767
bool DoPlayerInfoUpdate(C4ClientPlayerInfos *pUpdate)
bool ReloadParticle(const char *szName)
Definition: C4Game.cpp:2073
C4GraphicsSystem GraphicsSystem
Definition: C4Globals.cpp:51
const char * getLocalName() const
Definition: C4Client.h:170
C4ValueMapNames * pNames
Definition: C4ValueMap.h:44
virtual void ProcessChar(char &rChar)=0
C4Value ScenPropList
Definition: C4ScriptHost.h:163
bool SyncMode() const
C4ID GetScriptPlayerExtraID() const
Definition: C4PlayerInfo.h:178
void RemoveUnusedTexMapEntries()
void Begin() override
const char * GetLeagueProgressData() const
Definition: C4PlayerInfo.h:192
StdStrBuf GetKeysAsString(bool human_readable, bool short_name) const
void AddPlayer(class C4PlayerInfo &rInfo, bool fAdjustPlayer)
Definition: C4Teams.cpp:52
void Take(char *pnData)
Definition: StdBuf.h:457
bool Remove(int id)
Definition: C4Shader.cpp:740
bool DrawDefMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, const char *szMapDef, bool ignoreSky=false)
C4Team * GetTeamByIndex(int32_t iIndex) const
Definition: C4Teams.cpp:404
C4PlayerList Players
int32_t GetTemperature()
Definition: C4Weather.cpp:100
class C4Sky & GetSky()
C4ScriptFnDef C4ScriptGameFnMap[]
C4Object * PlaceAnimal(C4PropList *def)
Definition: C4Game.cpp:2772
C4ScriptGuiWindow * GetSubWindow(int32_t childID, C4Object *childTarget)
bool HostilityDeclared(int iPlayer1, int iPlayer2) const
bool DrawChunks(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, int32_t icntx, int32_t icnty, const char *szMaterial, const char *szTexture, bool bIFT)
void setTargetFPS(int32_t iToVal)
void Copy(const C4Value *Pars, int ParCount)
Definition: C4AulFunc.h:36
void SetMinZoom(C4Real zoom, bool no_increase, bool no_decrease)
Definition: C4Player.cpp:1823
const int32_t C4GM_VCenter
Definition: C4GameMessage.h:41
void Word(uint16_t &rShort) override
int32_t GetX() const
Definition: C4Object.h:286
bool IsCustom() const
Definition: C4Teams.h:163
const C4Value & getResult() const
virtual void ProcessInt(int32_t &rInt)=0
Definition: C4Def.h:98
void SetMusicMaxPositionMemory(int32_t val)
const int NO_OWNER
Definition: C4Constants.h:137
C4Fixed itofix(int32_t x)
Definition: C4Real.h:261
int32_t Hostile(int32_t plr1, int32_t plr2)
const char * GetName() const
Definition: C4Teams.h:65
void SetSize(int32_t inSize)
BYTE GetPix(int32_t x, int32_t y) const
StdCopyStrBuf NextMissionText
Definition: C4Game.h:146
void SetMaxZoomByViewRange(int32_t range_wdt, int32_t range_hgt, bool no_increase, bool no_decrease)
Definition: C4Player.cpp:1810
void HideSettlementScore(bool fHide=true)
const int32_t C4GM_GlobalPlayer
Definition: C4GameMessage.h:30
C4Draw * pDraw
Definition: C4Draw.cpp:42
const int32_t C4GM_Target
Definition: C4GameMessage.h:31
void SetViewOffset(int32_t x, int32_t y)
Definition: C4Viewport.h:91
C4Real GetGravity() const
bool ReloadDef(C4ID id)
Definition: C4Game.cpp:2015
void SetGlobalSoundModifier(C4PropList *modifier_props)
Definition: C4Game.cpp:3873
void ProcessChar(char &rChar) override
#define C4S_KEEP_EFFECTS
Definition: C4Scenario.h:50
C4Weather Weather
Definition: C4Weather.cpp:206
C4Object * GetObject(int Index=0) const
C4PXSSystem PXS
Definition: C4PXS.cpp:525
#define C4RGB(r, g, b)
Definition: StdColors.h:26
int32_t Num
Definition: C4Material.h:168
int32_t Status
Definition: C4PropList.h:168
int32_t MinHeightCount
Definition: C4Material.h:130
C4Value C4VArray(C4ValueArray *pArray)
Definition: C4Value.h:249
void SetViewLocked(bool to_val)
Definition: C4Player.cpp:1897
bool IsControlDisabled(int ctrl) const
bool SetKnowledge(C4ID id, bool fRemove)
Definition: C4Player.cpp:752
C4FoWAmbient Ambient
Definition: C4FoW.h:115
int32_t getLeagueScore() const
Definition: C4PlayerInfo.h:185
int32_t GetSeason()
Definition: C4Weather.cpp:132
C4PlayerControlDefs PlayerControlDefs
Definition: C4Game.h:92
const int32_t C4M_Solid
Definition: C4Constants.h:172
C4Team * GetTeamByPlayerID(int32_t iID) const
Definition: C4Teams.cpp:420
bool IsFrozen() const
Definition: C4PropList.h:131
Definition: C4Id.h:25
C4PlayerType
Definition: C4Constants.h:151
C4RoundResults & RoundResults
Definition: C4Game.h:73
const int32_t TEAMID_New
Definition: C4Teams.h:27
C4ObjectList Crew
Definition: C4Player.h:125
int32_t Eliminated
Definition: C4Player.h:83
void AbortMsgBoardQuery(C4Object *pObj, int32_t iPlr)
void SetDefaultGamma()
Definition: C4Game.cpp:3860
bool SortBy(int32_t iColKey, bool fReverse)
int32_t CurrentScore
Definition: C4Player.h:116
C4FindObject * CreateCriterionsFromPars(C4Value *pPars, C4FindObject **pFOs, C4SortObject **pSOs, const C4Object *context)
C4ParticleSystemDefinitionList definitions
Definition: C4Particles.h:510
int32_t ParX
Definition: C4Sky.h:57
bool DrawMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, const char *szMapDef, bool ignoreSky=false)
int32_t Wealth
Definition: C4Player.h:115
C4Object * FnPlaceAnimal(C4PropList *_this, C4PropList *Def)
C4Real ydir
Definition: C4Sky.h:55
bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
int32_t Count(const C4ObjectList &Objs)
C4LSectors Sectors
Definition: C4GameObjects.h:42
int32_t getInt() const
Definition: C4Value.h:112
int32_t ZoomLimitMinWdt
Definition: C4Player.h:112
C4Value C4VBool(bool b)
Definition: C4Value.h:243
int32_t GetItemNr(const char *strName) const
Definition: C4ValueMap.cpp:459
int32_t GetBackMat(int32_t x, int32_t y) const
int32_t SetGameMusicLevel(int32_t val)
int32_t GetHeight() const
size_t GetCount() const
int32_t ID
Definition: C4Player.h:87
void DWord(int32_t &rInt) override
C4Object * FnObject(C4PropList *_this, long iNumber)
void Ref(const char *pnData)
Definition: StdBuf.h:455
void Byte(int8_t &rByte) override
bool SetModulation(DWORD dwWithClr, DWORD dwBackClr)
Definition: C4Sky.cpp:229
int32_t ExtractMaterial(int32_t fx, int32_t fy, bool distant_first)
int ObjectCount(C4ID id=C4ID::None) const
C4Object * Object(C4PropList *_this)
Definition: C4AulDefFunc.h:34
void AddCustomEvaluationString(const char *szCustomString, int32_t idPlayer)
int32_t ZoomLimitMaxHgt
Definition: C4Player.h:112
bool DrawQuad(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iX3, int32_t iY3, int32_t iX4, int32_t iY4, const char *szMaterial, const char *szBackMaterial, bool fDrawBridge)
BYTE GetBackPix(int32_t x, int32_t y) const
const C4Value C4VNull
Definition: C4Value.cpp:30
void Set(const C4Value &value)
int32_t StartupPlayerCount
Definition: C4Game.h:109
void RemovePlayerByID(int32_t iID)
Definition: C4Teams.cpp:94
bool isDeserializer() override
C4PlayerInfoList & PlayerInfos
Definition: C4Game.h:71
int32_t Get(const char *szMaterial)
Definition: C4Material.cpp:361
C4Def * C4Id2Def(C4ID id)
Definition: C4DefList.h:84
C4ViewportList Viewports
Definition: C4Viewport.cpp:841
const char * GetTexture(int32_t iIndex)
Definition: C4Texture.cpp:494
const char * GetName() const
Definition: C4Player.h:151
const char * Identifier
Definition: C4AulDefFunc.h:268
StdCopyStrBuf ConsoleGroupPath
Definition: C4Def.h:177
bool GBackSemiSolid(int32_t x, int32_t y)
Definition: C4Landscape.h:236
void FlashMessage(const char *szMessage)
void Create(C4ParticleDef *of_def, C4ParticleValueProvider &x, C4ParticleValueProvider &y, C4ParticleValueProvider &speedX, C4ParticleValueProvider &speedY, C4ParticleValueProvider &lifetime, C4PropList *properties, int amount=1, C4Object *object=nullptr)
void SetGameTickDelay(int iDelay)
int32_t ParY
Definition: C4Sky.h:57
C4ScriptConstDef C4ScriptGameConstMap[]
C4ScriptShader ScriptShader
Definition: C4Shader.cpp:717
const int32_t C4MC_MD_DragSource
bool SetControlDisabled(int ctrl, bool is_disabled)
C4ValueMapNames * CreateTempNameList()
Definition: C4ValueMap.cpp:146
void SetTeamHostility()
Definition: C4Player.cpp:915
C4ValueCompiler(const char **pszNames, int iNameCnt, int iEntryNr)
C4GameControlNetwork Network
Definition: C4GameControl.h:67
C4PathFinder PathFinder
Definition: C4Game.h:84
const int32_t C4GM_WidthRel
Definition: C4GameMessage.h:43
const int32_t C4GM_Global
Definition: C4GameMessage.h:29
bool isReplay() const
Definition: C4GameControl.h:98
TeamDist GetTeamDist() const
Definition: C4Teams.h:208
int32_t ValidPlr(int32_t plr)
C4Real ZoomLimitMaxVal
Definition: C4Player.h:113
bool DoScore(int32_t iChange)
Definition: C4Player.cpp:1342
bool isVerbose() override
void Shrink(size_t iShrink)
Definition: StdBuf.h:503
C4SoundInstance * GetSoundInstance(const char *szSndName, C4Object *pObj)
int32_t GetCount() const
Definition: C4PXS.h:61
C4Object * SafeObjectPointer(int32_t iNumber)
bool WildcardMatch(const char *szWildcard, const char *szString)
Definition: StdFile.cpp:374
C4Value GetValByStdCompiler(const char *strEntry, const char *strSection, int iEntryNr, const T &rFrom)
void ResetCursorView(bool immediate_position=false)
Definition: C4Player.cpp:780
C4Value GRBroadcast(const char *szFunction, C4AulParSet *pPars=nullptr, bool fPassError=false, bool fRejectTest=false)
Definition: C4Game.cpp:3846
void ClearFreeRect(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt)
bool SetIDCount(C4ID c_id, int32_t iCount, bool fAddNewID=false)
Definition: stub-handle.cpp:68
bool CreateFromPropList(C4PropList *proplist, bool resetStdTag=false, bool isUpdate=false, bool isLoading=false)
C4MaterialMap MaterialMap
Definition: C4Material.cpp:969
bool Log(const char *szMessage)
Definition: C4Log.cpp:192
void Boolean(bool &rBool) override
C4Player * Next
Definition: C4Player.h:142
C4ValueGetCompiler(const char **pszNames, int iNameCnt, int iEntryNr)
void SetCell(int32_t iColKey, int32_t iRowKey, const char *szValue, int32_t iValue)
C4ClientList & Clients
Definition: C4Game.h:69
C4Effect * pScenarioEffects
Definition: C4ScriptHost.h:165
void Surrender()
Definition: C4Player.cpp:828
const int32_t C4GM_HCenter
Definition: C4GameMessage.h:40
const int32_t C4M_SemiSolid
Definition: C4Constants.h:173
#define PSF_RejectHostilityChange
Definition: C4GameScript.h:130
int32_t InitialScore
Definition: C4Player.h:116
C4Real xdir
Definition: C4Sky.h:55
#define C4S_SAVE_OBJECTS
Definition: C4Scenario.h:49
bool isLeague() const
bool ConstructionCheck(C4PropList *PropList, int32_t iX, int32_t iY, C4Object *pByObj)
C4Value C4VString(C4String *pStr)
Definition: C4Value.h:246
bool Name(const char *szName) override
void SetLeagueProgressData(const char *szNewProgressData)
Definition: C4PlayerInfo.h:139
void SetGravity(C4Real g)
C4Effect ** FnGetEffectsFor(C4PropList *pTarget)
void SetClimate(int32_t iClimate)
Definition: C4Weather.cpp:137
StdParameterAdapt< T, P > mkParAdapt(T &&rObj, P &&rPar)
Definition: StdAdaptors.h:458
const int32_t C4PVM_Target
Definition: C4Player.h:32
class C4ParticleList * FrontParticles
Definition: C4Object.h:158
int32_t StartupTeamCount
Definition: C4Game.h:110
int32_t GetTeamCount() const
Definition: C4Teams.h:158
C4ParticleList * GetGlobalParticles()
Definition: C4Particles.h:496
size_t getLength() const
Definition: StdBuf.h:445
C4Object * ViewTarget
Definition: C4Player.h:108
bool Default(const char *szName) override
C4DefList Definitions
Definition: C4Globals.cpp:49
void SetMinZoomByViewRange(int32_t range_wdt, int32_t range_hgt, bool no_increase, bool no_decrease)
Definition: C4Player.cpp:1803
void SetLength(size_t iLength)
Definition: StdBuf.h:509
C4PlayerType GetType() const
Definition: C4PlayerInfo.h:152
virtual void SetPropertyByS(C4String *k, const C4Value &to)
Definition: C4PropList.cpp:952
int32_t GetCellData(int32_t iColKey, int32_t iRowKey)
#define X(sdl, oc)
void Word(int16_t &rShort) override
void String(char *szString, size_t iMaxLength, RawCompileType eType) override
bool SetWealth(int32_t val)
Definition: C4Player.cpp:741
int32_t Hgt
Definition: C4Rect.h:30
bool IsJoin2TeamAllowed(int32_t idTeam, C4PlayerType plrType)
Definition: C4Teams.cpp:534
C4GameMessageList Messages
class C4SoundInstance * StartSoundEffectAt(const char *, int32_t, int32_t, int32_t, int32_t, int32_t, class C4SoundModifier *)
Definition: stub-handle.cpp:41
std::unique_ptr< C4ScriptGuiWindow > ScriptGuiRoot
Definition: C4Game.h:233
virtual void ProcessString(char *szString, size_t iMaxLength, bool fIsID)=0
void ProcessString(char *szString, size_t iMaxLength, bool fIsID) override
bool CtrlRemove(int iPlayer, bool fDisonnected)
C4ObjectPtr ViewCursor
Definition: C4Player.h:130
virtual void Update()
const int32_t C4M_Liquid
Definition: C4Constants.h:174
bool GainScenarioAchievement(const char *achievement_id, int32_t value, const char *scen_name_override=nullptr)
Definition: C4Player.cpp:1906
StdStrBuf FnStringFormat(C4PropList *_this, C4String *szFormatPar, C4Value *Pars, int ParCount)
Definition: C4Script.cpp:29
C4ID GetID(size_t index, int32_t *ipCount=nullptr) const
Definition: C4IDList.cpp:99
C4IDList BaseMaterial
Definition: C4Player.h:120
int Add(const std::string &shaderName, ShaderType type, const std::string &source)
Definition: C4Shader.cpp:728
uint32_t AsInt() const
C4ParticleDef * GetDef(const char *name, C4ParticleDef *exclude=nullptr)
int fixtoi(const C4Fixed &x)
Definition: C4Real.h:259
bool MatValid(int32_t mat)
Definition: C4Material.h:210
const int32_t C4GM_Left
Definition: C4GameMessage.h:38
int32_t Controller
Definition: C4Object.h:111
void AddFunc(C4PropListStatic *Parent, const char *Name, RType(*pFunc)(ThisType *, ParTypes...), bool Public=true)
Definition: C4AulDefFunc.h:260
void Copy()
Definition: StdBuf.h:467
C4Object * Find(const C4ObjectList &Objs)
C4String * GetPropertyStr(C4PropertyName k) const
Definition: C4PropList.cpp:775
C4Object * GetTarget()
bool Inside(T ival, U lbound, V rbound)
Definition: Standard.h:43
C4PropList * GetPropertyPropList(C4PropertyName k) const
Definition: C4PropList.cpp:900
bool hasNaming() override
bool IsHostilityChangeAllowed() const
Definition: C4Teams.h:164
bool SAddModule(char *szList, const char *szModule, bool fCaseSensitive)
Definition: Standard.cpp:557
void SetGamma(float r, float g, float b, int32_t iRampIndex)
Definition: C4Draw.cpp:744
void Decompile(const T &rStruct)
Definition: StdCompiler.h:178
C4Object * PlaceVegetation(C4PropList *def, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iGrowth, C4PropList *shape_proplist, C4PropList *out_pos_proplist)
Definition: C4Game.cpp:2649
const int32_t C4M_Background
Definition: C4Constants.h:175
C4Application Application
Definition: C4Globals.cpp:44
virtual void ProcessBool(bool &rBool)=0
int32_t GBackMat(int32_t x, int32_t y)
Definition: C4Landscape.h:221
void SetSeason(int32_t iSeason)
Definition: C4Weather.cpp:126
void GameMsgObject(const char *szText, C4Object *pTarget)
static C4TimeMilliseconds Now()
bool GBackLiquid(int32_t x, int32_t y)
Definition: C4Landscape.h:241
int32_t GetWidth() const
C4Object * CreateObject(C4PropList *type, C4Object *pCreator, int32_t owner=NO_OWNER, int32_t x=50, int32_t y=50, int32_t r=0, bool grow_from_center=false, C4Real xdir=Fix0, C4Real ydir=Fix0, C4Real rdir=Fix0, int32_t iController=NO_OWNER)
Definition: C4Game.cpp:1072
void SetSoundModifier(C4PropList *new_modifier)
Definition: C4Player.cpp:1922
void String(std::string &str, RawCompileType type) override
int32_t PixCol2Tex(BYTE pixc)
Definition: C4Landscape.h:213
C4Effect * pGlobalEffects
Definition: C4Aul.h:144
bool New(int32_t iType, const StdStrBuf &Text, C4Object *pTarget, int32_t iPlayer, int32_t iX=-1, int32_t iY=-1, uint32_t dwClr=0xffFFFFFF, C4ID idDecoID=C4ID::None, C4PropList *pSrc=nullptr, uint32_t dwFlags=0u, int32_t width=0)
C4IDList BaseProduction
Definition: C4Player.h:121
C4GameObjects Objects
Definition: C4Globals.cpp:48
int32_t GetWind(int32_t x, int32_t y)
Definition: C4Weather.cpp:94
bool SetHostility(int32_t iOpponent, int32_t iHostility, bool fSilent=false)
Definition: C4Player.cpp:838
bool GBackSolid(int32_t x, int32_t y)
Definition: C4Landscape.h:231
C4String * GetTranslatedString(const class C4Value &input_string, C4Value *selected_language, bool fail_silently) const
Definition: C4Game.cpp:3890
void BlastFree(int32_t tx, int32_t ty, int32_t rad, int32_t caused_by=NO_OWNER, C4Object *by_object=nullptr, int32_t iMaxDensity=C4M_Vehicle)
static C4PropList * New(C4PropList *prototype=nullptr)
Definition: C4PropList.cpp:64
bool RemoveMessageBoardQuery(C4Object *pForObj)
Definition: C4Player.cpp:1673
int iSize
Definition: TstC4NetIO.cpp:32
bool LocalControl
Definition: C4Player.h:99
bool Play(const char *szSongname=nullptr, bool fLoop=false, int fadetime_ms=0, double max_resume_time=0.0, bool allow_break=false)
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
C4PlayerType GetType() const
Definition: C4Player.cpp:1726
C4Real ZoomLimitMinVal
Definition: C4Player.h:113
C4MusicSystem MusicSystem
Definition: C4Application.h:41
C4PropList * getPropList() const
Definition: C4Value.h:116