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