1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** $Id: vc_object.cpp 4297 2010-06-03 22:49:00Z firebrand_kh $
11 //**
12 //** Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //** This program is free software; you can redistribute it and/or
15 //** modify it under the terms of the GNU General Public License
16 //** as published by the Free Software Foundation; either version 2
17 //** of the License, or (at your option) any later version.
18 //**
19 //** This program is distributed in the hope that it will be useful,
20 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 //** GNU General Public License for more details.
23 //**
24 //**************************************************************************
25
26 #include "gamedefs.h"
27 #include "network.h"
28
29 // Register a class at startup time.
30 VClass VObject::PrivateStaticClass
31 (
32 EC_NativeConstructor,
33 sizeof(VObject),
34 VObject::StaticClassFlags,
35 NULL,
36 NAME_Object,
37 VObject::InternalConstructor
38 );
39 VClass* autoclassVObject = VObject::StaticClass();
40
41 bool VObject::GObjInitialised;
42 TArray<VObject*> VObject::GObjObjects;
43 TArray<int> VObject::GObjAvailable;
44 VObject* VObject::GObjHash[4096];
45 int VObject::GNumDeleted;
46 bool VObject::GInGarbageCollection;
47 void* VObject::GNewObject;
48
49 //==========================================================================
50 //
51 // VObject::VObject
52 //
53 //==========================================================================
54
VObject()55 VObject::VObject()
56 {
57 }
58
59 //==========================================================================
60 //
61 // VObject::~VObject
62 //
63 //==========================================================================
64
~VObject()65 VObject::~VObject()
66 {
67 guard(VObject::~VObject);
68 ConditionalDestroy();
69 GNumDeleted--;
70 if (!GObjInitialised)
71 {
72 return;
73 }
74
75 if (!GInGarbageCollection)
76 {
77 SetFlags(_OF_CleanupRef);
78 for (int i = 0; i < GObjObjects.Num(); i++)
79 {
80 if (!GObjObjects[i] || GObjObjects[i]->GetFlags() & _OF_Destroyed)
81 {
82 continue;
83 }
84 GObjObjects[i]->GetClass()->CleanObject(GObjObjects[i]);
85 }
86 }
87
88 if (Index == GObjObjects.Num() - 1)
89 {
90 GObjObjects.RemoveIndex(Index);
91 }
92 else
93 {
94 GObjObjects[Index] = NULL;
95 GObjAvailable.Append(Index);
96 }
97 unguard;
98 }
99
100 //==========================================================================
101 //
102 // VObject::StaticInit
103 //
104 //==========================================================================
105
106 #ifdef ZONE_DEBUG_NEW
107 #undef new
108 #endif
109
operator new(size_t)110 void* VObject::operator new(size_t)
111 {
112 check(GNewObject);
113 return GNewObject;
114 }
115
116 //==========================================================================
117 //
118 // VObject::StaticInit
119 //
120 //==========================================================================
121
operator new(size_t,const char *,int)122 void* VObject::operator new(size_t, const char*, int)
123 {
124 check(GNewObject);
125 return GNewObject;
126 }
127
128 #ifdef ZONE_DEBUG_NEW
129 #define new ZONE_DEBUG_NEW
130 #endif
131
132 //==========================================================================
133 //
134 // VObject::StaticInit
135 //
136 //==========================================================================
137
operator delete(void * Object)138 void VObject::operator delete(void* Object)
139 {
140 Z_Free(Object);
141 }
142
143 //==========================================================================
144 //
145 // VObject::StaticInit
146 //
147 //==========================================================================
148
operator delete(void * Object,const char *,int)149 void VObject::operator delete(void* Object, const char*, int)
150 {
151 Z_Free(Object);
152 }
153
154 //==========================================================================
155 //
156 // VObject::StaticInit
157 //
158 //==========================================================================
159
StaticInit()160 void VObject::StaticInit()
161 {
162 VMemberBase::StaticInit();
163 GObjInitialised = true;
164 }
165
166 //==========================================================================
167 //
168 // VObject::StaticExit
169 //
170 //==========================================================================
171
StaticExit()172 void VObject::StaticExit()
173 {
174 for (int i = 0; i < GObjObjects.Num(); i++)
175 {
176 if (GObjObjects[i])
177 {
178 GObjObjects[i]->ConditionalDestroy();
179 }
180 }
181 CollectGarbage();
182 GObjObjects.Clear();
183 GObjAvailable.Clear();
184 GObjInitialised = false;
185 VMemberBase::StaticExit();
186 }
187
188 //==========================================================================
189 //
190 // VObject::StaticSpawnObject
191 //
192 //==========================================================================
193
StaticSpawnObject(VClass * AClass)194 VObject* VObject::StaticSpawnObject(VClass* AClass)
195 {
196 guard(VObject::StaticSpawnObject);
197 check(AClass);
198 // Allocate memory.
199 VObject* Obj = (VObject*)Z_Calloc(AClass->ClassSize);
200
201 // Copy values from the default object.
202 check(AClass->Defaults);
203 AClass->CopyObject(AClass->Defaults, (vuint8*)Obj);
204
205 // Find native class.
206 VClass* NativeClass = AClass;
207 while (NativeClass && !(NativeClass->ObjectFlags & CLASSOF_Native))
208 {
209 NativeClass = NativeClass->GetSuperClass();
210 }
211 check(NativeClass);
212
213 // Call constructor of the native class to set up C++ virtual table.
214 GNewObject = Obj;
215 NativeClass->ClassConstructor();
216 GNewObject = NULL;
217
218 // Set up object fields.
219 Obj->Class = AClass;
220 Obj->vtable = AClass->ClassVTable;
221 Obj->Register();
222
223 // We're done.
224 return Obj;
225 unguardf(("%s", AClass ? AClass->GetName() : "NULL"));
226 }
227
228 //==========================================================================
229 //
230 // VObject::Register
231 //
232 //==========================================================================
233
Register()234 void VObject::Register()
235 {
236 guard(VObject::Register);
237 if (GObjAvailable.Num())
238 {
239 Index = GObjAvailable[GObjAvailable.Num() - 1];
240 GObjAvailable.RemoveIndex(GObjAvailable.Num() - 1);
241 GObjObjects[Index] = this;
242 }
243 else
244 {
245 Index = GObjObjects.Append(this);
246 }
247 unguard;
248 }
249
250 //==========================================================================
251 //
252 // VObject::ConditionalDestroy
253 //
254 //==========================================================================
255
ConditionalDestroy()256 bool VObject::ConditionalDestroy()
257 {
258 if (!(ObjectFlags & _OF_Destroyed))
259 {
260 GNumDeleted++;
261 SetFlags(_OF_Destroyed);
262 Destroy();
263 }
264 return true;
265 }
266
267 //==========================================================================
268 //
269 // VObject::Destroy
270 //
271 //==========================================================================
272
Destroy()273 void VObject::Destroy()
274 {
275 Class->DestructObject(this);
276 }
277
278 //==========================================================================
279 //
280 // VObject::IsA
281 //
282 //==========================================================================
283
IsA(VClass * SomeBaseClass) const284 bool VObject::IsA(VClass *SomeBaseClass) const
285 {
286 for (const VClass *c = Class; c; c = c->GetSuperClass())
287 {
288 if (SomeBaseClass == c)
289 {
290 return true;
291 }
292 }
293 return false;
294 }
295
296 //==========================================================================
297 //
298 // VObject::GetVFunction
299 //
300 //==========================================================================
301
GetVFunction(VName FuncName) const302 VMethod *VObject::GetVFunction(VName FuncName) const
303 {
304 guardSlow(VObject::GetVFunction);
305 return vtable[Class->GetMethodIndex(FuncName)];
306 unguardSlow;
307 }
308
309 //==========================================================================
310 //
311 // VObject::ClearReferences
312 //
313 //==========================================================================
314
ClearReferences()315 void VObject::ClearReferences()
316 {
317 guard(VObject::ClearReferences);
318 GetClass()->CleanObject(this);
319 unguard;
320 }
321
322 //==========================================================================
323 //
324 // VObject::CollectGarbage
325 //
326 //==========================================================================
327
CollectGarbage()328 void VObject::CollectGarbage()
329 {
330 guard(VObject::CollectGarbage);
331 if (!GNumDeleted)
332 {
333 return;
334 }
335
336 GInGarbageCollection = true;
337 // Mark objects to be cleaned.
338 for (int i = 0; i < GObjObjects.Num(); i++)
339 {
340 if (!GObjObjects[i])
341 {
342 continue;
343 }
344 VObject *Obj = GObjObjects[i];
345 if (Obj->GetFlags() & _OF_Destroyed)
346 {
347 Obj->SetFlags(_OF_CleanupRef);
348 }
349 }
350
351 // Clean references.
352 for (int i = 0; i < GObjObjects.Num(); i++)
353 {
354 if (!GObjObjects[i] || GObjObjects[i]->GetFlags() & _OF_Destroyed)
355 {
356 continue;
357 }
358 GObjObjects[i]->ClearReferences();
359 }
360
361 // Now actually delete the objects.
362 for (int i = 0; i < GObjObjects.Num(); i++)
363 {
364 if (!GObjObjects[i])
365 {
366 continue;
367 }
368 VObject *Obj = GObjObjects[i];
369 if (Obj->GetFlags() & _OF_Destroyed)
370 {
371 delete Obj;
372 Obj = NULL;
373 }
374 }
375 GInGarbageCollection = false;
376 unguard;
377 }
378
379 //==========================================================================
380 //
381 // VObject::GetIndexObject
382 //
383 //==========================================================================
384
GetIndexObject(int Index)385 VObject *VObject::GetIndexObject(int Index)
386 {
387 return GObjObjects[Index];
388 }
389
390 //==========================================================================
391 //
392 // VObject::GetObjectsCount
393 //
394 //==========================================================================
395
GetObjectsCount()396 int VObject::GetObjectsCount()
397 {
398 return GObjObjects.Num();
399 }
400
401 //==========================================================================
402 //
403 // VObject::Serialise
404 //
405 //==========================================================================
406
Serialise(VStream & Strm)407 void VObject::Serialise(VStream& Strm)
408 {
409 guard(VObject::Serialise);
410 GetClass()->SerialiseObject(Strm, this);
411 unguard;
412 }
413
414 //==========================================================================
415 //
416 // VObject::ExecuteNetMethod
417 //
418 //==========================================================================
419
ExecuteNetMethod(VMethod *)420 bool VObject::ExecuteNetMethod(VMethod*)
421 {
422 return false;
423 }
424
425 //==========================================================================
426 //
427 // Object.Destroy
428 //
429 //==========================================================================
430
IMPLEMENT_FUNCTION(VObject,Destroy)431 IMPLEMENT_FUNCTION(VObject, Destroy)
432 {
433 P_GET_SELF;
434 delete Self;
435 Self = NULL;
436 }
437
438 //==========================================================================
439 //
440 // Object.IsA
441 //
442 //==========================================================================
443
IMPLEMENT_FUNCTION(VObject,IsA)444 IMPLEMENT_FUNCTION(VObject, IsA)
445 {
446 P_GET_NAME(SomeName);
447 P_GET_SELF;
448 bool Ret = false;
449 for (const VClass *c = Self->Class; c; c = c->GetSuperClass())
450 {
451 if (c->GetVName() == SomeName)
452 {
453 Ret = true;
454 break;
455 }
456 }
457 RET_BOOL(Ret);
458 }
459
460 //==========================================================================
461 //
462 // Object.IsDestroyed
463 //
464 //==========================================================================
465
IMPLEMENT_FUNCTION(VObject,IsDestroyed)466 IMPLEMENT_FUNCTION(VObject, IsDestroyed)
467 {
468 P_GET_SELF;
469 RET_BOOL(Self->GetFlags() & _OF_DelayedDestroy);
470 }
471
472 //**************************************************************************
473 //
474 // Error functions
475 //
476 //**************************************************************************
477
IMPLEMENT_FUNCTION(VObject,Error)478 IMPLEMENT_FUNCTION(VObject, Error)
479 {
480 Host_Error("%s", *PF_FormatString());
481 }
482
IMPLEMENT_FUNCTION(VObject,FatalError)483 IMPLEMENT_FUNCTION(VObject, FatalError)
484 {
485 Sys_Error("%s", *PF_FormatString());
486 }
487
488 //**************************************************************************
489 //
490 // Cvar functions
491 //
492 //**************************************************************************
493
IMPLEMENT_FUNCTION(VObject,CreateCvar)494 IMPLEMENT_FUNCTION(VObject, CreateCvar)
495 {
496 P_GET_INT(flags);
497 P_GET_STR(def);
498 P_GET_NAME(name);
499 new VCvar(*name, def, flags);
500 }
501
IMPLEMENT_FUNCTION(VObject,GetCvar)502 IMPLEMENT_FUNCTION(VObject, GetCvar)
503 {
504 P_GET_NAME(name);
505 RET_INT(VCvar::GetInt(*name));
506 }
507
IMPLEMENT_FUNCTION(VObject,SetCvar)508 IMPLEMENT_FUNCTION(VObject, SetCvar)
509 {
510 P_GET_INT(value);
511 P_GET_NAME(name);
512 VCvar::Set(*name, value);
513 }
514
IMPLEMENT_FUNCTION(VObject,GetCvarF)515 IMPLEMENT_FUNCTION(VObject, GetCvarF)
516 {
517 P_GET_NAME(name);
518 RET_FLOAT(VCvar::GetFloat(*name));
519 }
520
IMPLEMENT_FUNCTION(VObject,SetCvarF)521 IMPLEMENT_FUNCTION(VObject, SetCvarF)
522 {
523 P_GET_FLOAT(value);
524 P_GET_NAME(name);
525 VCvar::Set(*name, value);
526 }
527
IMPLEMENT_FUNCTION(VObject,GetCvarS)528 IMPLEMENT_FUNCTION(VObject, GetCvarS)
529 {
530 P_GET_NAME(name);
531 RET_STR(VCvar::GetString(*name));
532 }
533
IMPLEMENT_FUNCTION(VObject,SetCvarS)534 IMPLEMENT_FUNCTION(VObject, SetCvarS)
535 {
536 P_GET_STR(value);
537 P_GET_NAME(name);
538 VCvar::Set(*name, value);
539 }
540
541 //**************************************************************************
542 //
543 // Math functions
544 //
545 //**************************************************************************
546
IMPLEMENT_FUNCTION(VObject,AngleMod360)547 IMPLEMENT_FUNCTION(VObject, AngleMod360)
548 {
549 P_GET_FLOAT(an);
550 RET_FLOAT(AngleMod(an));
551 }
552
IMPLEMENT_FUNCTION(VObject,AngleMod180)553 IMPLEMENT_FUNCTION(VObject, AngleMod180)
554 {
555 P_GET_FLOAT(an);
556 RET_FLOAT(AngleMod180(an));
557 }
558
IMPLEMENT_FUNCTION(VObject,abs)559 IMPLEMENT_FUNCTION(VObject, abs)
560 {
561 P_GET_INT(i);
562 RET_INT(abs(i));
563 }
564
IMPLEMENT_FUNCTION(VObject,fabs)565 IMPLEMENT_FUNCTION(VObject, fabs)
566 {
567 P_GET_FLOAT(i);
568 RET_FLOAT(fabs(i));
569 }
570
IMPLEMENT_FUNCTION(VObject,Min)571 IMPLEMENT_FUNCTION(VObject, Min)
572 {
573 P_GET_INT(v2);
574 P_GET_INT(v1);
575 RET_INT(MIN(v1, v2));
576 }
577
IMPLEMENT_FUNCTION(VObject,FMin)578 IMPLEMENT_FUNCTION(VObject, FMin)
579 {
580 P_GET_FLOAT(v2);
581 P_GET_FLOAT(v1);
582 RET_FLOAT(MIN(v1, v2));
583 }
584
IMPLEMENT_FUNCTION(VObject,Max)585 IMPLEMENT_FUNCTION(VObject, Max)
586 {
587 P_GET_INT(v2);
588 P_GET_INT(v1);
589 RET_INT(MAX(v1, v2));
590 }
591
IMPLEMENT_FUNCTION(VObject,FMax)592 IMPLEMENT_FUNCTION(VObject, FMax)
593 {
594 P_GET_FLOAT(v2);
595 P_GET_FLOAT(v1);
596 RET_FLOAT(MAX(v1, v2));
597 }
598
IMPLEMENT_FUNCTION(VObject,Clamp)599 IMPLEMENT_FUNCTION(VObject, Clamp)
600 {
601 P_GET_INT(Max);
602 P_GET_INT(Min);
603 P_GET_INT(Val);
604 RET_INT(MID(Min, Val, Max));
605 }
606
IMPLEMENT_FUNCTION(VObject,FClamp)607 IMPLEMENT_FUNCTION(VObject, FClamp)
608 {
609 P_GET_FLOAT(Max);
610 P_GET_FLOAT(Min);
611 P_GET_FLOAT(Val);
612 RET_FLOAT(MID(Min, Val, Max));
613 }
614
IMPLEMENT_FUNCTION(VObject,sin)615 IMPLEMENT_FUNCTION(VObject, sin)
616 {
617 P_GET_FLOAT(an);
618 RET_FLOAT(msin(an));
619 }
620
IMPLEMENT_FUNCTION(VObject,cos)621 IMPLEMENT_FUNCTION(VObject, cos)
622 {
623 P_GET_FLOAT(an);
624 RET_FLOAT(mcos(an));
625 }
626
IMPLEMENT_FUNCTION(VObject,tan)627 IMPLEMENT_FUNCTION(VObject, tan)
628 {
629 P_GET_FLOAT(an);
630 RET_FLOAT(mtan(an));
631 }
632
IMPLEMENT_FUNCTION(VObject,asin)633 IMPLEMENT_FUNCTION(VObject, asin)
634 {
635 P_GET_FLOAT(x);
636 RET_FLOAT(masin(x));
637 }
638
IMPLEMENT_FUNCTION(VObject,acos)639 IMPLEMENT_FUNCTION(VObject, acos)
640 {
641 P_GET_FLOAT(x);
642 RET_FLOAT(acos(x));
643 }
644
IMPLEMENT_FUNCTION(VObject,atan)645 IMPLEMENT_FUNCTION(VObject, atan)
646 {
647 P_GET_FLOAT(slope);
648 RET_FLOAT(RAD2DEG(atan(slope)));
649 }
650
IMPLEMENT_FUNCTION(VObject,atan2)651 IMPLEMENT_FUNCTION(VObject, atan2)
652 {
653 P_GET_FLOAT(x);
654 P_GET_FLOAT(y);
655 RET_FLOAT(matan(y, x));
656 }
657
IMPLEMENT_FUNCTION(VObject,sqrt)658 IMPLEMENT_FUNCTION(VObject, sqrt)
659 {
660 P_GET_FLOAT(x);
661 RET_FLOAT(sqrt(x));
662 }
663
IMPLEMENT_FUNCTION(VObject,Length)664 IMPLEMENT_FUNCTION(VObject, Length)
665 {
666 P_GET_VEC(vec);
667 RET_FLOAT(Length(vec));
668 }
669
IMPLEMENT_FUNCTION(VObject,Normalise)670 IMPLEMENT_FUNCTION(VObject, Normalise)
671 {
672 P_GET_VEC(vec);
673 RET_VEC(Normalise(vec));
674 }
675
IMPLEMENT_FUNCTION(VObject,DotProduct)676 IMPLEMENT_FUNCTION(VObject, DotProduct)
677 {
678 P_GET_VEC(v2);
679 P_GET_VEC(v1);
680 RET_FLOAT(DotProduct(v1, v2));
681 }
682
IMPLEMENT_FUNCTION(VObject,CrossProduct)683 IMPLEMENT_FUNCTION(VObject, CrossProduct)
684 {
685 P_GET_VEC(v2);
686 P_GET_VEC(v1);
687 RET_VEC(CrossProduct(v1, v2));
688 }
689
IMPLEMENT_FUNCTION(VObject,AngleVectors)690 IMPLEMENT_FUNCTION(VObject, AngleVectors)
691 {
692 P_GET_PTR(TVec, vup);
693 P_GET_PTR(TVec, vright);
694 P_GET_PTR(TVec, vforward);
695 P_GET_PTR(TAVec, angles);
696 AngleVectors(*angles, *vforward, *vright, *vup);
697 }
698
IMPLEMENT_FUNCTION(VObject,AngleVector)699 IMPLEMENT_FUNCTION(VObject, AngleVector)
700 {
701 P_GET_PTR(TVec, vec);
702 P_GET_PTR(TAVec, angles);
703 AngleVector(*angles, *vec);
704 }
705
IMPLEMENT_FUNCTION(VObject,VectorAngles)706 IMPLEMENT_FUNCTION(VObject, VectorAngles)
707 {
708 P_GET_PTR(TAVec, angles);
709 P_GET_PTR(TVec, vec);
710 VectorAngles(*vec, *angles);
711 }
712
IMPLEMENT_FUNCTION(VObject,GetPlanePointZ)713 IMPLEMENT_FUNCTION(VObject, GetPlanePointZ)
714 {
715 P_GET_VEC(point);
716 P_GET_PTR(TPlane, plane);
717 RET_FLOAT(plane->GetPointZ(point));
718 }
719
IMPLEMENT_FUNCTION(VObject,PointOnPlaneSide)720 IMPLEMENT_FUNCTION(VObject, PointOnPlaneSide)
721 {
722 P_GET_PTR(TPlane, plane);
723 P_GET_VEC(point);
724 RET_INT(plane->PointOnSide(point));
725 }
726
IMPLEMENT_FUNCTION(VObject,RotateDirectionVector)727 IMPLEMENT_FUNCTION(VObject, RotateDirectionVector)
728 {
729 P_GET_AVEC(rot);
730 P_GET_VEC(vec);
731
732 TAVec angles;
733 TVec out;
734
735 VectorAngles(vec, angles);
736 angles.pitch += rot.pitch;
737 angles.yaw += rot.yaw;
738 angles.roll += rot.roll;
739 AngleVector(angles, out);
740 RET_VEC(out);
741 }
742
IMPLEMENT_FUNCTION(VObject,VectorRotateAroundZ)743 IMPLEMENT_FUNCTION(VObject, VectorRotateAroundZ)
744 {
745 P_GET_FLOAT(angle);
746 P_GET_PTR(TVec, vec);
747
748 float dstx = vec->x * mcos(angle) - vec->y * msin(angle);
749 float dsty = vec->x * msin(angle) + vec->y * mcos(angle);
750
751 vec->x = dstx;
752 vec->y = dsty;
753 }
754
IMPLEMENT_FUNCTION(VObject,RotateVectorAroundVector)755 IMPLEMENT_FUNCTION(VObject, RotateVectorAroundVector)
756 {
757 P_GET_FLOAT(Angle);
758 P_GET_VEC(Axis);
759 P_GET_VEC(Vector);
760 RET_VEC(RotateVectorAroundVector(Vector, Axis, Angle));
761 }
762
763 //**************************************************************************
764 //
765 // String functions
766 //
767 //**************************************************************************
768
IMPLEMENT_FUNCTION(VObject,strlen)769 IMPLEMENT_FUNCTION(VObject, strlen)
770 {
771 P_GET_STR(s);
772 RET_INT(s.Utf8Length());
773 }
774
IMPLEMENT_FUNCTION(VObject,strcmp)775 IMPLEMENT_FUNCTION(VObject, strcmp)
776 {
777 P_GET_STR(s2);
778 P_GET_STR(s1);
779 RET_INT(s1.Cmp(s2));
780 }
781
IMPLEMENT_FUNCTION(VObject,stricmp)782 IMPLEMENT_FUNCTION(VObject, stricmp)
783 {
784 P_GET_STR(s2);
785 P_GET_STR(s1);
786 RET_INT(s1.ICmp(s2));
787 }
788
IMPLEMENT_FUNCTION(VObject,strcat)789 IMPLEMENT_FUNCTION(VObject, strcat)
790 {
791 P_GET_STR(s2);
792 P_GET_STR(s1);
793 RET_STR(s1 + s2);
794 }
795
IMPLEMENT_FUNCTION(VObject,strlwr)796 IMPLEMENT_FUNCTION(VObject, strlwr)
797 {
798 P_GET_STR(s);
799 RET_STR(s.ToLower());
800 }
801
IMPLEMENT_FUNCTION(VObject,strupr)802 IMPLEMENT_FUNCTION(VObject, strupr)
803 {
804 P_GET_STR(s);
805 RET_STR(s.ToUpper());
806 }
807
IMPLEMENT_FUNCTION(VObject,substr)808 IMPLEMENT_FUNCTION(VObject, substr)
809 {
810 P_GET_INT(Len);
811 P_GET_INT(Start);
812 P_GET_STR(Str);
813 RET_STR(Str.Utf8Substring(Start, Len));
814 }
815
IMPLEMENT_FUNCTION(VObject,va)816 IMPLEMENT_FUNCTION(VObject, va)
817 {
818 RET_STR(PF_FormatString());
819 }
820
IMPLEMENT_FUNCTION(VObject,atoi)821 IMPLEMENT_FUNCTION(VObject, atoi)
822 {
823 P_GET_STR(str);
824 RET_INT(atoi(*str));
825 }
826
IMPLEMENT_FUNCTION(VObject,atof)827 IMPLEMENT_FUNCTION(VObject, atof)
828 {
829 P_GET_STR(str);
830 RET_FLOAT(atof(*str));
831 }
832
IMPLEMENT_FUNCTION(VObject,StrStartsWith)833 IMPLEMENT_FUNCTION(VObject, StrStartsWith)
834 {
835 P_GET_STR(Check);
836 P_GET_STR(Str);
837 RET_BOOL(Str.StartsWith(Check));
838 }
839
IMPLEMENT_FUNCTION(VObject,StrEndsWith)840 IMPLEMENT_FUNCTION(VObject, StrEndsWith)
841 {
842 P_GET_STR(Check);
843 P_GET_STR(Str);
844 RET_BOOL(Str.EndsWith(Check));
845 }
846
IMPLEMENT_FUNCTION(VObject,StrReplace)847 IMPLEMENT_FUNCTION(VObject, StrReplace)
848 {
849 P_GET_STR(Replacement);
850 P_GET_STR(Search);
851 P_GET_STR(Str);
852 RET_STR(Str.Replace(Search, Replacement));
853 }
854
855 //**************************************************************************
856 //
857 // Random numbers
858 //
859 //**************************************************************************
860
IMPLEMENT_FUNCTION(VObject,Random)861 IMPLEMENT_FUNCTION(VObject, Random)
862 {
863 RET_FLOAT(Random());
864 }
865
IMPLEMENT_FUNCTION(VObject,P_Random)866 IMPLEMENT_FUNCTION(VObject, P_Random)
867 {
868 RET_INT(rand() & 0xff);
869 }
870
871 //**************************************************************************
872 //
873 // Texture utils
874 //
875 //**************************************************************************
876
IMPLEMENT_FUNCTION(VObject,CheckTextureNumForName)877 IMPLEMENT_FUNCTION(VObject, CheckTextureNumForName)
878 {
879 P_GET_NAME(name);
880 RET_INT(GTextureManager.CheckNumForName(name, TEXTYPE_Wall, true, false));
881 }
882
IMPLEMENT_FUNCTION(VObject,TextureNumForName)883 IMPLEMENT_FUNCTION(VObject, TextureNumForName)
884 {
885 P_GET_NAME(name);
886 RET_INT(GTextureManager.NumForName(name, TEXTYPE_Wall, true, false));
887 }
888
IMPLEMENT_FUNCTION(VObject,CheckFlatNumForName)889 IMPLEMENT_FUNCTION(VObject, CheckFlatNumForName)
890 {
891 P_GET_NAME(name);
892 RET_INT(GTextureManager.CheckNumForName(name, TEXTYPE_Flat, true, false));
893 }
894
IMPLEMENT_FUNCTION(VObject,FlatNumForName)895 IMPLEMENT_FUNCTION(VObject, FlatNumForName)
896 {
897 P_GET_NAME(name);
898 RET_INT(GTextureManager.NumForName(name, TEXTYPE_Flat, true, false));
899 }
900
IMPLEMENT_FUNCTION(VObject,TextureHeight)901 IMPLEMENT_FUNCTION(VObject, TextureHeight)
902 {
903 P_GET_INT(pic);
904 RET_FLOAT(GTextureManager.TextureHeight(pic));
905 }
906
IMPLEMENT_FUNCTION(VObject,GetTextureName)907 IMPLEMENT_FUNCTION(VObject, GetTextureName)
908 {
909 P_GET_INT(Handle);
910 RET_NAME(GTextureManager.GetTextureName(Handle));
911 }
912
913 //==========================================================================
914 //
915 // Printing in console
916 //
917 //==========================================================================
918
IMPLEMENT_FUNCTION(VObject,print)919 IMPLEMENT_FUNCTION(VObject, print)
920 {
921 GCon->Log(PF_FormatString());
922 }
923
IMPLEMENT_FUNCTION(VObject,dprint)924 IMPLEMENT_FUNCTION(VObject, dprint)
925 {
926 GCon->Log(NAME_Dev, PF_FormatString());
927 }
928
929 //==========================================================================
930 //
931 // Type conversions
932 //
933 //==========================================================================
934
IMPLEMENT_FUNCTION(VObject,itof)935 IMPLEMENT_FUNCTION(VObject, itof)
936 {
937 P_GET_INT(x);
938 RET_FLOAT((float)x);
939 }
940
IMPLEMENT_FUNCTION(VObject,ftoi)941 IMPLEMENT_FUNCTION(VObject, ftoi)
942 {
943 P_GET_FLOAT(x);
944 RET_INT((vint32)x);
945 }
946
IMPLEMENT_FUNCTION(VObject,StrToName)947 IMPLEMENT_FUNCTION(VObject, StrToName)
948 {
949 P_GET_STR(str);
950 RET_NAME(VName(*str));
951 }
952
953 //==========================================================================
954 //
955 // Console command functions
956 //
957 //==========================================================================
958
IMPLEMENT_FUNCTION(VObject,Cmd_CheckParm)959 IMPLEMENT_FUNCTION(VObject, Cmd_CheckParm)
960 {
961 P_GET_STR(str);
962 RET_INT(VCommand::CheckParm(*str));
963 }
964
IMPLEMENT_FUNCTION(VObject,CmdBuf_AddText)965 IMPLEMENT_FUNCTION(VObject, CmdBuf_AddText)
966 {
967 GCmdBuf << PF_FormatString();
968 }
969
970 //==========================================================================
971 //
972 // Class methods
973 //
974 //==========================================================================
975
IMPLEMENT_FUNCTION(VObject,FindClass)976 IMPLEMENT_FUNCTION(VObject, FindClass)
977 {
978 P_GET_NAME(Name);
979 RET_PTR(VClass::FindClass(*Name));
980 }
981
IMPLEMENT_FUNCTION(VObject,FindClassLowerCase)982 IMPLEMENT_FUNCTION(VObject, FindClassLowerCase)
983 {
984 P_GET_NAME(Name);
985 RET_PTR(VClass::FindClassLowerCase(Name));
986 }
987
IMPLEMENT_FUNCTION(VObject,ClassIsChildOf)988 IMPLEMENT_FUNCTION(VObject, ClassIsChildOf)
989 {
990 P_GET_PTR(VClass, BaseClass);
991 P_GET_PTR(VClass, SomeClass);
992 RET_BOOL(SomeClass->IsChildOf(BaseClass));
993 }
994
IMPLEMENT_FUNCTION(VObject,GetClassName)995 IMPLEMENT_FUNCTION(VObject, GetClassName)
996 {
997 P_GET_PTR(VClass, SomeClass);
998 RET_NAME(SomeClass->Name);
999 }
1000
IMPLEMENT_FUNCTION(VObject,GetClassParent)1001 IMPLEMENT_FUNCTION(VObject, GetClassParent)
1002 {
1003 P_GET_PTR(VClass, SomeClass);
1004 RET_PTR(SomeClass->ParentClass);
1005 }
1006
IMPLEMENT_FUNCTION(VObject,GetClassReplacement)1007 IMPLEMENT_FUNCTION(VObject, GetClassReplacement)
1008 {
1009 P_GET_PTR(VClass, SomeClass);
1010 RET_PTR(SomeClass->GetReplacement());
1011 }
1012
IMPLEMENT_FUNCTION(VObject,GetClassReplacee)1013 IMPLEMENT_FUNCTION(VObject, GetClassReplacee)
1014 {
1015 P_GET_PTR(VClass, SomeClass);
1016 RET_PTR(SomeClass->GetReplacee());
1017 }
1018
IMPLEMENT_FUNCTION(VObject,FindClassState)1019 IMPLEMENT_FUNCTION(VObject, FindClassState)
1020 {
1021 P_GET_NAME(StateName);
1022 P_GET_PTR(VClass, Cls);
1023 VStateLabel* Lbl = Cls->FindStateLabel(StateName);
1024 RET_PTR(Lbl ? Lbl->State : NULL);
1025 }
1026
IMPLEMENT_FUNCTION(VObject,GetClassNumOwnedStates)1027 IMPLEMENT_FUNCTION(VObject, GetClassNumOwnedStates)
1028 {
1029 P_GET_PTR(VClass, Cls);
1030 int Ret = 0;
1031 for (VState* S = Cls->States; S; S = S->Next)
1032 {
1033 Ret++;
1034 }
1035 RET_INT(Ret);
1036 }
1037
IMPLEMENT_FUNCTION(VObject,GetClassFirstState)1038 IMPLEMENT_FUNCTION(VObject, GetClassFirstState)
1039 {
1040 P_GET_PTR(VClass, Cls);
1041 RET_PTR(Cls->States);
1042 }
1043
1044 //==========================================================================
1045 //
1046 // State methods
1047 //
1048 //==========================================================================
1049
IMPLEMENT_FUNCTION(VObject,StateIsInRange)1050 IMPLEMENT_FUNCTION(VObject, StateIsInRange)
1051 {
1052 P_GET_INT(MaxDepth);
1053 P_GET_PTR(VState, End);
1054 P_GET_PTR(VState, Start);
1055 P_GET_PTR(VState, State);
1056 RET_BOOL(State->IsInRange(Start, End, MaxDepth));
1057 }
1058
IMPLEMENT_FUNCTION(VObject,StateIsInSequence)1059 IMPLEMENT_FUNCTION(VObject, StateIsInSequence)
1060 {
1061 P_GET_PTR(VState, Start);
1062 P_GET_PTR(VState, State);
1063 RET_BOOL(State->IsInSequence(Start));
1064 }
1065
IMPLEMENT_FUNCTION(VObject,GetStateSpriteName)1066 IMPLEMENT_FUNCTION(VObject, GetStateSpriteName)
1067 {
1068 P_GET_PTR(VState, State);
1069 RET_NAME(State ? State->SpriteName : NAME_None);
1070 }
1071
IMPLEMENT_FUNCTION(VObject,GetStateDuration)1072 IMPLEMENT_FUNCTION(VObject, GetStateDuration)
1073 {
1074 P_GET_PTR(VState, State);
1075 RET_FLOAT(State ? State->Time : 0.0);
1076 }
1077
IMPLEMENT_FUNCTION(VObject,GetStatePlus)1078 IMPLEMENT_FUNCTION(VObject, GetStatePlus)
1079 {
1080 P_GET_BOOL_OPT(IgnoreJump, false);
1081 P_GET_INT(Offset);
1082 P_GET_PTR(VState, State);
1083 RET_PTR(State->GetPlus(Offset, IgnoreJump));
1084 }
1085
IMPLEMENT_FUNCTION(VObject,AreStateSpritesPresent)1086 IMPLEMENT_FUNCTION(VObject, AreStateSpritesPresent)
1087 {
1088 P_GET_PTR(VState, State);
1089 RET_BOOL(State ? R_AreSpritesPresent(State->SpriteIndex) : false);
1090 }
1091
1092 //==========================================================================
1093 //
1094 // Iterators
1095 //
1096 //==========================================================================
1097
1098 class VObjectsIterator : public VScriptIterator
1099 {
1100 private:
1101 VClass* BaseClass;
1102 VObject** Out;
1103 int Index;
1104
1105 public:
VObjectsIterator(VClass * ABaseClass,VObject ** AOut)1106 VObjectsIterator(VClass* ABaseClass, VObject** AOut)
1107 : BaseClass(ABaseClass)
1108 , Out(AOut)
1109 , Index(0)
1110 {
1111 }
GetNext()1112 bool GetNext()
1113 {
1114 while (Index < VObject::GetObjectsCount())
1115 {
1116 VObject* Check = VObject::GetIndexObject(Index);
1117 Index++;
1118 if (Check && !(Check->GetFlags() & _OF_DelayedDestroy) &&
1119 Check->IsA(BaseClass))
1120 {
1121 *Out = Check;
1122 return true;
1123 }
1124 }
1125 *Out = NULL;
1126 return false;
1127 }
1128 };
1129
IMPLEMENT_FUNCTION(VObject,AllObjects)1130 IMPLEMENT_FUNCTION(VObject, AllObjects)
1131 {
1132 P_GET_PTR(VObject*, Obj);
1133 P_GET_PTR(VClass, BaseClass);
1134 RET_PTR(new VObjectsIterator(BaseClass, Obj));
1135 }
1136
1137 class VClassesIterator : public VScriptIterator
1138 {
1139 private:
1140 VClass* BaseClass;
1141 VClass** Out;
1142 int Index;
1143
1144 public:
VClassesIterator(VClass * ABaseClass,VClass ** AOut)1145 VClassesIterator(VClass* ABaseClass, VClass** AOut)
1146 : BaseClass(ABaseClass)
1147 , Out(AOut)
1148 , Index(0)
1149 {
1150 }
GetNext()1151 bool GetNext()
1152 {
1153 while (Index < VMemberBase::GMembers.Num())
1154 {
1155 VMemberBase* Check = VMemberBase::GMembers[Index];
1156 Index++;
1157 if (Check->MemberType == MEMBER_Class &&
1158 ((VClass*)Check)->IsChildOf(BaseClass))
1159 {
1160 *Out = (VClass*)Check;
1161 return true;
1162 }
1163 }
1164 *Out = NULL;
1165 return false;
1166 }
1167 };
1168
IMPLEMENT_FUNCTION(VObject,AllClasses)1169 IMPLEMENT_FUNCTION(VObject, AllClasses)
1170 {
1171 P_GET_PTR(VClass*, Class);
1172 P_GET_PTR(VClass, BaseClass);
1173 RET_PTR(new VClassesIterator(BaseClass, Class));
1174 }
1175
1176 //==========================================================================
1177 //
1178 // Misc
1179 //
1180 //==========================================================================
1181
IMPLEMENT_FUNCTION(VObject,Info_ValueForKey)1182 IMPLEMENT_FUNCTION(VObject, Info_ValueForKey)
1183 {
1184 P_GET_STR(key);
1185 P_GET_STR(info);
1186 RET_STR(Info_ValueForKey(info, key));
1187 }
1188
IMPLEMENT_FUNCTION(VObject,WadLumpPresent)1189 IMPLEMENT_FUNCTION(VObject, WadLumpPresent)
1190 {
1191 P_GET_NAME(name);
1192 RET_BOOL(W_CheckNumForName(name) >= 0);
1193 }
1194
IMPLEMENT_FUNCTION(VObject,SpawnObject)1195 IMPLEMENT_FUNCTION(VObject, SpawnObject)
1196 {
1197 P_GET_PTR(VClass, Class);
1198 RET_REF(VObject::StaticSpawnObject(Class));
1199 }
1200
IMPLEMENT_FUNCTION(VObject,FindAnimDoor)1201 IMPLEMENT_FUNCTION(VObject, FindAnimDoor)
1202 {
1203 P_GET_INT(BaseTex);
1204 RET_PTR(R_FindAnimDoor(BaseTex));
1205 }
1206
IMPLEMENT_FUNCTION(VObject,GetLangString)1207 IMPLEMENT_FUNCTION(VObject, GetLangString)
1208 {
1209 P_GET_NAME(Id);
1210 RET_STR(GLanguage[Id]);
1211 }
1212
IMPLEMENT_FUNCTION(VObject,RGB)1213 IMPLEMENT_FUNCTION(VObject, RGB)
1214 {
1215 P_GET_BYTE(b);
1216 P_GET_BYTE(g);
1217 P_GET_BYTE(r);
1218 RET_INT(0xff000000 + (r << 16) + (g << 8) + b);
1219 }
1220
IMPLEMENT_FUNCTION(VObject,RGBA)1221 IMPLEMENT_FUNCTION(VObject, RGBA)
1222 {
1223 P_GET_BYTE(a);
1224 P_GET_BYTE(b);
1225 P_GET_BYTE(g);
1226 P_GET_BYTE(r);
1227 RET_INT((a << 24) + (r << 16) + (g << 8) + b);
1228 }
1229
IMPLEMENT_FUNCTION(VObject,GetLockDef)1230 IMPLEMENT_FUNCTION(VObject, GetLockDef)
1231 {
1232 P_GET_INT(Lock);
1233 RET_PTR(GetLockDef(Lock));
1234 }
1235
IMPLEMENT_FUNCTION(VObject,ParseColour)1236 IMPLEMENT_FUNCTION(VObject, ParseColour)
1237 {
1238 P_GET_STR(Name);
1239 RET_INT(M_ParseColour(Name));
1240 }
1241
IMPLEMENT_FUNCTION(VObject,TextColourString)1242 IMPLEMENT_FUNCTION(VObject, TextColourString)
1243 {
1244 P_GET_INT(Colour);
1245 VStr Ret;
1246 Ret += TEXT_COLOUR_ESCAPE;
1247 Ret += Colour < CR_BRICK || Colour >= NUM_TEXT_COLOURS ? '-' :
1248 (char)(Colour + 'A');
1249 RET_STR(Ret);
1250 }
1251
IMPLEMENT_FUNCTION(VObject,StartTitleMap)1252 IMPLEMENT_FUNCTION(VObject, StartTitleMap)
1253 {
1254 RET_BOOL(Host_StartTitleMap());
1255 }
1256
IMPLEMENT_FUNCTION(VObject,LoadBinaryLump)1257 IMPLEMENT_FUNCTION(VObject, LoadBinaryLump)
1258 {
1259 P_GET_PTR(TArray<vuint8>, Array);
1260 P_GET_NAME(LumpName);
1261 W_LoadLumpIntoArray(LumpName, *Array);
1262 }
1263
IMPLEMENT_FUNCTION(VObject,IsMapPresent)1264 IMPLEMENT_FUNCTION(VObject, IsMapPresent)
1265 {
1266 P_GET_NAME(MapName);
1267 RET_BOOL(IsMapPresent(MapName));
1268 }
1269
IMPLEMENT_FUNCTION(VObject,Clock)1270 IMPLEMENT_FUNCTION(VObject, Clock)
1271 {
1272 P_GET_INT(Idx);
1273 if (Idx < 0)
1274 host_cycles[-Idx]++;
1275 else
1276 clock(host_cycles[Idx]);
1277 }
1278
IMPLEMENT_FUNCTION(VObject,Unclock)1279 IMPLEMENT_FUNCTION(VObject, Unclock)
1280 {
1281 P_GET_INT(Idx);
1282 unclock(host_cycles[Idx]);
1283 }
1284