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