1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: p_entity.cpp 4001 2009-03-03 20:22:11Z dj_jl $
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 // HEADER FILES ------------------------------------------------------------
27 
28 #include "gamedefs.h"
29 //#include "sv_local.h"
30 
31 // MACROS ------------------------------------------------------------------
32 
33 // TYPES -------------------------------------------------------------------
34 
35 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
36 
37 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
38 
39 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
40 
41 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
42 
43 // PUBLIC DATA DEFINITIONS -------------------------------------------------
44 
45 IMPLEMENT_CLASS(V, Entity);
46 
47 // PRIVATE DATA DEFINITIONS ------------------------------------------------
48 
49 int VEntity::FIndex_OnMapSpawn;
50 int VEntity::FIndex_BeginPlay;
51 int VEntity::FIndex_Destroyed;
52 int VEntity::FIndex_Touch;
53 int VEntity::FIndex_BlastedHitLine;
54 int VEntity::FIndex_CheckForPushSpecial;
55 int VEntity::FIndex_ApplyFriction;
56 int VEntity::FIndex_HandleFloorclip;
57 int VEntity::FIndex_CrossSpecialLine;
58 int VEntity::FIndex_SectorChanged;
59 int VEntity::FIndex_RoughCheckThing;
60 int VEntity::FIndex_GiveInventory;
61 int VEntity::FIndex_TakeInventory;
62 int VEntity::FIndex_CheckInventory;
63 int VEntity::FIndex_GetSigilPieces;
64 int VEntity::FIndex_MoveThing;
65 int VEntity::FIndex_GetStateTime;
66 
67 // CODE --------------------------------------------------------------------
68 
69 //==========================================================================
70 //
71 //	VEntity::InitFuncIndexes
72 //
73 //==========================================================================
74 
InitFuncIndexes()75 void VEntity::InitFuncIndexes()
76 {
77 	guard(VEntity::InitFuncIndexes);
78 	FIndex_OnMapSpawn = StaticClass()->GetMethodIndex(NAME_OnMapSpawn);
79 	FIndex_BeginPlay = StaticClass()->GetMethodIndex(NAME_BeginPlay);
80 	FIndex_Destroyed = StaticClass()->GetMethodIndex(NAME_Destroyed);
81 	FIndex_Touch = StaticClass()->GetMethodIndex(NAME_Touch);
82 	FIndex_BlastedHitLine = StaticClass()->GetMethodIndex(NAME_BlastedHitLine);
83 	FIndex_CheckForPushSpecial = StaticClass()->GetMethodIndex(NAME_CheckForPushSpecial);
84 	FIndex_ApplyFriction = StaticClass()->GetMethodIndex(NAME_ApplyFriction);
85 	FIndex_HandleFloorclip = StaticClass()->GetMethodIndex(NAME_HandleFloorclip);
86 	FIndex_CrossSpecialLine = StaticClass()->GetMethodIndex(NAME_CrossSpecialLine);
87 	FIndex_SectorChanged = StaticClass()->GetMethodIndex(NAME_SectorChanged);
88 	FIndex_RoughCheckThing = StaticClass()->GetMethodIndex(NAME_RoughCheckThing);
89 	FIndex_GiveInventory = StaticClass()->GetMethodIndex(NAME_GiveInventory);
90 	FIndex_TakeInventory = StaticClass()->GetMethodIndex(NAME_TakeInventory);
91 	FIndex_CheckInventory = StaticClass()->GetMethodIndex(NAME_CheckInventory);
92 	FIndex_GetSigilPieces = StaticClass()->GetMethodIndex(NAME_GetSigilPieces);
93 	FIndex_MoveThing = StaticClass()->GetMethodIndex(NAME_MoveThing);
94 	FIndex_GetStateTime = StaticClass()->GetMethodIndex(NAME_GetStateTime);
95 	unguard;
96 }
97 
98 //==========================================================================
99 //
100 //  VEntity::Serialise
101 //
102 //==========================================================================
103 
Serialise(VStream & Strm)104 void VEntity::Serialise(VStream& Strm)
105 {
106 	guard(VEntity::Serialise);
107 	Super::Serialise(Strm);
108 
109 	if (Strm.IsLoading())
110 	{
111 		if (EntityFlags & EF_IsPlayer)
112 		{
113 			Player->MO = this;
114 		}
115 		SubSector = NULL;	//	Must mark as not linked
116 		LinkToWorld();
117 	}
118 	unguard;
119 }
120 
121 //==========================================================================
122 //
123 //	VEntity::DestroyThinker
124 //
125 //==========================================================================
126 
DestroyThinker()127 void VEntity::DestroyThinker()
128 {
129 	guard(VEntity::DestroyThinker)
130 	if (Role == ROLE_Authority)
131 	{
132 		eventDestroyed();
133 
134 		if (TID)
135 		{
136 			// Remove from TID list
137 			RemoveFromTIDList();
138 		}
139 
140 		// stop any playing sound
141 		StopSound(0);
142 	}
143 
144 	// unlink from sector and block lists
145 	UnlinkFromWorld();
146 	XLevel->DelSectorList();
147 
148 	Super::DestroyThinker();
149 	unguard;
150 }
151 
152 //==========================================================================
153 //
154 //	VEntity::AddedToLevel
155 //
156 //==========================================================================
157 
AddedToLevel()158 void VEntity::AddedToLevel()
159 {
160 	guard(VEntity::AddedToLevel);
161 	if (!XLevel->NextSoundOriginID)
162 	{
163 		XLevel->NextSoundOriginID = 1;
164 	}
165 	SoundOriginID = XLevel->NextSoundOriginID + (SNDORG_Entity << 24);
166 	XLevel->NextSoundOriginID = (XLevel->NextSoundOriginID + 1) & 0x00ffffff;
167 	unguard;
168 }
169 
170 //==========================================================================
171 //
172 //	VEntity::SetTID
173 //
174 //==========================================================================
175 
SetTID(int tid)176 void VEntity::SetTID(int tid)
177 {
178 	guard(VEntity::SetTID);
179 	RemoveFromTIDList();
180 	if (tid)
181 	{
182 		InsertIntoTIDList(tid);
183 	}
184 	unguard;
185 }
186 
187 //==========================================================================
188 //
189 //	VEntity::InsertIntoTIDList
190 //
191 //==========================================================================
192 
InsertIntoTIDList(int tid)193 void VEntity::InsertIntoTIDList(int tid)
194 {
195 	guard(VEntity::InsertIntoTIDList);
196 	TID = tid;
197 	int HashIndex = tid & (VLevelInfo::TID_HASH_SIZE - 1);
198 	TIDHashPrev = NULL;
199 	TIDHashNext = Level->TIDHash[HashIndex];
200 	if (TIDHashNext)
201 	{
202 		TIDHashNext->TIDHashPrev = this;
203 	}
204 	Level->TIDHash[HashIndex] = this;
205 	unguard;
206 }
207 
208 //==========================================================================
209 //
210 //	VEntity::RemoveFromTIDList
211 //
212 //==========================================================================
213 
RemoveFromTIDList()214 void VEntity::RemoveFromTIDList()
215 {
216 	guard(VEntity::RemoveFromTIDList);
217 	if (!TID)
218 	{
219 		//	No TID, which means it's not in the cache.
220 		return;
221 	}
222 
223 	if (TIDHashNext)
224 	{
225 		TIDHashNext->TIDHashPrev = TIDHashPrev;
226 	}
227 	if (TIDHashPrev)
228 	{
229 		TIDHashPrev->TIDHashNext = TIDHashNext;
230 	}
231 	else
232 	{
233 		int HashIndex = TID & (VLevelInfo::TID_HASH_SIZE - 1);
234 		check(Level->TIDHash[HashIndex] == this);
235 		Level->TIDHash[HashIndex] = TIDHashNext;
236 	}
237 	TID = 0;
238 	unguard;
239 }
240 
241 //==========================================================================
242 //
243 //  VEntity::SetState
244 //
245 //  Returns true if the actor is still present.
246 //
247 //==========================================================================
248 
SetState(VState * InState)249 bool VEntity::SetState(VState* InState)
250 {
251 	guard(VEntity::SetState);
252 	VState *st = InState;
253 	do
254 	{
255 		if (!st)
256 		{
257 			// Remove mobj
258 			State = NULL;
259 			StateTime = -1;
260 			DestroyThinker();
261 			return false;
262 		}
263 
264 		if (st->SpriteIndex == 1)
265 		{
266 			//	1 is ----, which is "do not change sprite"
267 			if (!(EntityFlags & EF_UseDispState))
268 			{
269 				DispState = State;
270 				EntityFlags |= EF_UseDispState;
271 			}
272 		}
273 		else
274 		{
275 			EntityFlags &= ~EF_UseDispState;
276 		}
277 		State = st;
278 		StateTime = eventGetStateTime(st, st->Time);
279 		EntityFlags &= ~EF_FullBright;
280 
281 		// Modified handling.
282 		// Call action functions when the state is set
283 		if (st->Function)
284 		{
285 			XLevel->CallingState = State;
286 			P_PASS_SELF;
287 			ExecuteFunction(st->Function);
288 		}
289 
290 		if (!State)
291 		{
292 			return false;
293 		}
294 		st = State->NextState;
295 	}
296 	while (!StateTime);
297 	return true;
298 	unguard;
299 }
300 
301 //==========================================================================
302 //
303 //  VEntity::SetInitialState
304 //
305 //  Returns true if the actor is still present.
306 //
307 //==========================================================================
308 
SetInitialState(VState * InState)309 void VEntity::SetInitialState(VState* InState)
310 {
311 	guard(VEntity::SetInitialState);
312 	State = InState;
313 	if (InState)
314 	{
315 		StateTime = eventGetStateTime(InState, InState->Time);
316 	}
317 	else
318 	{
319 		StateTime = -1.0;
320 	}
321 	unguard;
322 }
323 
324 //==========================================================================
325 //
326 //	VEntity::AdvanceState
327 //
328 //==========================================================================
329 
AdvanceState(float deltaTime)330 bool VEntity::AdvanceState(float deltaTime)
331 {
332 	guard(VEntity::AdvanceState);
333 	if (State && StateTime != -1.0)
334 	{
335 		StateTime -= deltaTime;
336 		// you can cycle through multiple states in a tic
337 		if (StateTime <= 0.0)
338 		{
339 			if (!SetState(State->NextState))
340 			{
341 				return false;	// freed itself
342 			}
343 		}
344 	}
345 	return true;
346 	unguard;
347 }
348 
349 //==========================================================================
350 //
351 //	VEntity::FindState
352 //
353 //==========================================================================
354 
FindState(VName StateName,VName SubLabel,bool Exact)355 VState* VEntity::FindState(VName StateName, VName SubLabel, bool Exact)
356 {
357 	guard(VEntity::FindState);
358 	VStateLabel* Lbl = GetClass()->FindStateLabel(StateName, SubLabel, Exact);
359 	return Lbl ? Lbl->State : NULL;
360 	unguard;
361 }
362 
363 //==========================================================================
364 //
365 //	VEntity::FindStateEx
366 //
367 //==========================================================================
368 
FindStateEx(const VStr & StateName,bool Exact)369 VState* VEntity::FindStateEx(const VStr& StateName, bool Exact)
370 {
371 	guard(VEntity::FindStateEx);
372 	TArray<VName> Names;
373 	VMemberBase::StaticSplitStateLabel(StateName, Names);
374 	VStateLabel* Lbl = GetClass()->FindStateLabel(Names, Exact);
375 	return Lbl ? Lbl->State : NULL;
376 	unguard;
377 }
378 
379 //==========================================================================
380 //
381 //	VEntity::HasSpecialStates
382 //
383 //==========================================================================
384 
HasSpecialStates(VName StateName)385 bool VEntity::HasSpecialStates(VName StateName)
386 {
387 	guard(VEntity::HasSpecialStates);
388 	VStateLabel* Lbl = GetClass()->FindStateLabel(StateName);
389 	return Lbl && Lbl->SubLabels.Num() > 0;
390 	unguard;
391 }
392 
393 //==========================================================================
394 //
395 //	VEntity::GetStateEffects
396 //
397 //==========================================================================
398 
GetStateEffects(TArray<VLightEffectDef * > & Lights,TArray<VParticleEffectDef * > & Part) const399 void VEntity::GetStateEffects(TArray<VLightEffectDef*>& Lights,
400 	TArray<VParticleEffectDef*>& Part) const
401 {
402 	guard(VEntity::GetStateEffects);
403 	//	Clear arrays.
404 	Lights.Clear();
405 
406 	//	Check for valid state
407 	if (!State)
408 	{
409 		return;
410 	}
411 
412 	//	Find all matching effects.
413 	for (int i = 0; i < GetClass()->SpriteEffects.Num(); i++)
414 	{
415 		VSpriteEffect& SprFx = GetClass()->SpriteEffects[i];
416 		if (SprFx.SpriteIndex != State->SpriteIndex)
417 		{
418 			continue;
419 		}
420 		if (SprFx.Frame != -1 &&
421 			SprFx.Frame != (State->Frame & VState::FF_FRAMEMASK))
422 		{
423 			continue;
424 		}
425 
426 		if (SprFx.LightDef)
427 		{
428 			Lights.Append(SprFx.LightDef);
429 		}
430 		if (SprFx.PartDef)
431 		{
432 			Part.Append(SprFx.PartDef);
433 		}
434 	}
435 	unguard;
436 }
437 
438 //==========================================================================
439 //
440 //	VEntity::CallStateChain
441 //
442 //==========================================================================
443 
CallStateChain(VEntity * Actor,VState * AState)444 bool VEntity::CallStateChain(VEntity* Actor, VState* AState)
445 {
446 	guard(VEntity::CallStateChain);
447 	//	Set up state call structure.
448 	VStateCall* PrevCall = XLevel->StateCall;
449 	VStateCall Call;
450 	Call.Item = this;
451 	bool Ret = false;
452 	XLevel->StateCall = &Call;
453 
454 	int RunAway = 0;
455 	VState* S = AState;
456 	while (S)
457 	{
458 		Call.State = S;
459 		//	Call action function.
460 		if (S->Function)
461 		{
462 			//	Assume success by default.
463 			XLevel->CallingState = S;
464 			Call.Result = true;
465 			P_PASS_REF(Actor);
466 			ExecuteFunction(S->Function);
467 			//	At least one success means overal success.
468 			if (Call.Result)
469 			{
470 				Ret = true;
471 			}
472 		}
473 
474 		//	Check for infinite loops
475 		RunAway++;
476 		if (RunAway > 1000)
477 		{
478 			break;
479 		}
480 
481 		if (Call.State == S)
482 		{
483 			//	Abort immediately if next state loops to itself. In this case
484 			// the overal result is always false.
485 			if (S->NextState == S)
486 			{
487 				Ret = false;
488 				break;
489 			}
490 			//	Advance to the next state.
491 			S = S->NextState;
492 		}
493 		else
494 		{
495 			//	There was a state jump.
496 			S = Call.State;
497 		}
498 	}
499 
500 	XLevel->StateCall = PrevCall;
501 	return Ret;
502 	unguard;
503 }
504 
505 //==========================================================================
506 //
507 //	VEntity::StartSound
508 //
509 //==========================================================================
510 
StartSound(VName Sound,vint32 Channel,float Volume,float Attenuation,bool Loop)511 void VEntity::StartSound(VName Sound, vint32 Channel, float Volume,
512 	float Attenuation, bool Loop)
513 {
514 	guard(VEntity::StartSound);
515 	if (Sector->SectorFlags & sector_t::SF_Silent)
516 	{
517 		return;
518 	}
519 	Super::StartSound(Origin, SoundOriginID,
520 		GSoundManager->ResolveEntitySound(SoundClass, SoundGender, Sound),
521 		Channel, Volume, Attenuation, Loop);
522 	unguard;
523 }
524 
525 //==========================================================================
526 //
527 //	VEntity::StartLocalSound
528 //
529 //==========================================================================
530 
StartLocalSound(VName Sound,vint32 Channel,float Volume,float Attenuation)531 void VEntity::StartLocalSound(VName Sound, vint32 Channel, float Volume,
532 	float Attenuation)
533 {
534 	guard(VEntity::StartLocalSound);
535 	if (Sector->SectorFlags & sector_t::SF_Silent)
536 	{
537 		return;
538 	}
539 	if (Player)
540 	{
541 		Player->eventClientStartSound(
542 			GSoundManager->ResolveEntitySound(SoundClass, SoundGender, Sound),
543 			TVec(0, 0, 0), 0, Channel, Volume, Attenuation, false);
544 	}
545 	unguard;
546 }
547 
548 //==========================================================================
549 //
550 //	VEntity::StopSound
551 //
552 //==========================================================================
553 
StopSound(vint32 channel)554 void VEntity::StopSound(vint32 channel)
555 {
556 	guard(VEntity::StopSound);
557 	Super::StopSound(SoundOriginID, channel);
558 	unguard;
559 }
560 
561 //==========================================================================
562 //
563 //	VEntity::StartSoundSequence
564 //
565 //==========================================================================
566 
StartSoundSequence(VName Name,vint32 ModeNum)567 void VEntity::StartSoundSequence(VName Name, vint32 ModeNum)
568 {
569 	guard(VEntity::StartSoundSequence);
570 	if (Sector->SectorFlags & sector_t::SF_Silent)
571 	{
572 		return;
573 	}
574 	Super::StartSoundSequence(Origin, SoundOriginID, Name, ModeNum);
575 	unguard;
576 }
577 
578 //==========================================================================
579 //
580 //	VEntity::AddSoundSequenceChoice
581 //
582 //==========================================================================
583 
AddSoundSequenceChoice(VName Choice)584 void VEntity::AddSoundSequenceChoice(VName Choice)
585 {
586 	guard(VEntity::AddSoundSequenceChoice);
587 	if (Sector->SectorFlags & sector_t::SF_Silent)
588 	{
589 		return;
590 	}
591 	Super::AddSoundSequenceChoice(SoundOriginID, Choice);
592 	unguard;
593 }
594 
595 //==========================================================================
596 //
597 //	VEntity::StopSoundSequence
598 //
599 //==========================================================================
600 
StopSoundSequence()601 void VEntity::StopSoundSequence()
602 {
603 	guard(VEntity::StopSoundSequence);
604 	Super::StopSoundSequence(SoundOriginID);
605 	unguard;
606 }
607 
608 //==========================================================================
609 //
610 //	Script natives
611 //
612 //==========================================================================
613 
IMPLEMENT_FUNCTION(VEntity,SetTID)614 IMPLEMENT_FUNCTION(VEntity, SetTID)
615 {
616 	P_GET_INT(tid);
617 	P_GET_SELF;
618 	Self->SetTID(tid);
619 }
620 
IMPLEMENT_FUNCTION(VEntity,SetState)621 IMPLEMENT_FUNCTION(VEntity, SetState)
622 {
623 	P_GET_PTR(VState, state);
624 	P_GET_SELF;
625 	RET_BOOL(Self->SetState(state));
626 }
627 
IMPLEMENT_FUNCTION(VEntity,SetInitialState)628 IMPLEMENT_FUNCTION(VEntity, SetInitialState)
629 {
630 	P_GET_PTR(VState, state);
631 	P_GET_SELF;
632 	Self->SetInitialState(state);
633 }
634 
IMPLEMENT_FUNCTION(VEntity,AdvanceState)635 IMPLEMENT_FUNCTION(VEntity, AdvanceState)
636 {
637 	P_GET_FLOAT(deltaTime);
638 	P_GET_SELF;
639 	RET_BOOL(Self->AdvanceState(deltaTime));
640 }
641 
IMPLEMENT_FUNCTION(VEntity,FindState)642 IMPLEMENT_FUNCTION(VEntity, FindState)
643 {
644 	P_GET_BOOL_OPT(Exact, false);
645 	P_GET_NAME_OPT(SubLabel, NAME_None);
646 	P_GET_NAME(StateName);
647 	P_GET_SELF;
648 	RET_PTR(Self->FindState(StateName, SubLabel, Exact));
649 }
650 
IMPLEMENT_FUNCTION(VEntity,FindStateEx)651 IMPLEMENT_FUNCTION(VEntity, FindStateEx)
652 {
653 	P_GET_BOOL_OPT(Exact, false);
654 	P_GET_STR(StateName);
655 	P_GET_SELF;
656 	RET_PTR(Self->FindStateEx(StateName, Exact));
657 }
658 
IMPLEMENT_FUNCTION(VEntity,HasSpecialStates)659 IMPLEMENT_FUNCTION(VEntity, HasSpecialStates)
660 {
661 	P_GET_NAME(StateName);
662 	P_GET_SELF;
663 	RET_BOOL(Self->HasSpecialStates(StateName));
664 }
665 
IMPLEMENT_FUNCTION(VEntity,GetStateEffects)666 IMPLEMENT_FUNCTION(VEntity, GetStateEffects)
667 {
668 	P_GET_PTR(TArray<VParticleEffectDef*>, Part);
669 	P_GET_PTR(TArray<VLightEffectDef*>, Lights);
670 	P_GET_SELF;
671 	Self->GetStateEffects(*Lights, *Part);
672 }
673 
IMPLEMENT_FUNCTION(VEntity,CallStateChain)674 IMPLEMENT_FUNCTION(VEntity, CallStateChain)
675 {
676 	P_GET_PTR(VState, State);
677 	P_GET_REF(VEntity, Actor);
678 	P_GET_SELF;
679 	RET_BOOL(Self->CallStateChain(Actor, State));
680 }
681 
IMPLEMENT_FUNCTION(VEntity,PlaySound)682 IMPLEMENT_FUNCTION(VEntity, PlaySound)
683 {
684 	P_GET_BOOL_OPT(Loop, false);
685 	P_GET_FLOAT_OPT(Attenuation, 1.0);
686 	P_GET_FLOAT_OPT(Volume, 1.0);
687 	P_GET_INT(Channel);
688 	P_GET_NAME(SoundName);
689 	P_GET_SELF;
690 	Self->StartSound(SoundName, Channel, Volume, Attenuation, Loop);
691 }
692 
IMPLEMENT_FUNCTION(VEntity,StopSound)693 IMPLEMENT_FUNCTION(VEntity, StopSound)
694 {
695 	P_GET_INT(Channel);
696 	P_GET_SELF;
697 	Self->StopSound(Channel);
698 }
699 
IMPLEMENT_FUNCTION(VEntity,AreSoundsEquivalent)700 IMPLEMENT_FUNCTION(VEntity, AreSoundsEquivalent)
701 {
702 	P_GET_NAME(Sound2);
703 	P_GET_NAME(Sound1);
704 	P_GET_SELF;
705 	RET_BOOL(GSoundManager->ResolveEntitySound(Self->SoundClass,
706 		Self->SoundGender, Sound1) == GSoundManager->ResolveEntitySound(
707 		Self->SoundClass, Self->SoundGender, Sound2));
708 }
709 
IMPLEMENT_FUNCTION(VEntity,IsSoundPresent)710 IMPLEMENT_FUNCTION(VEntity, IsSoundPresent)
711 {
712 	P_GET_NAME(Sound);
713 	P_GET_SELF;
714 	RET_BOOL(GSoundManager->IsSoundPresent(Self->SoundClass,
715 		Self->SoundGender, Sound));
716 }
717 
IMPLEMENT_FUNCTION(VEntity,StartSoundSequence)718 IMPLEMENT_FUNCTION(VEntity, StartSoundSequence)
719 {
720 	P_GET_INT(ModeNum);
721 	P_GET_NAME(Name);
722 	P_GET_SELF;
723 	Self->StartSoundSequence(Name, ModeNum);
724 }
725 
IMPLEMENT_FUNCTION(VEntity,AddSoundSequenceChoice)726 IMPLEMENT_FUNCTION(VEntity, AddSoundSequenceChoice)
727 {
728 	P_GET_NAME(Choice);
729 	P_GET_SELF;
730 	Self->AddSoundSequenceChoice(Choice);
731 }
732 
IMPLEMENT_FUNCTION(VEntity,StopSoundSequence)733 IMPLEMENT_FUNCTION(VEntity, StopSoundSequence)
734 {
735 	P_GET_SELF;
736 	Self->StopSoundSequence();
737 }
738 
IMPLEMENT_FUNCTION(VEntity,SetDecorateFlag)739 IMPLEMENT_FUNCTION(VEntity, SetDecorateFlag)
740 {
741 	P_GET_BOOL(Value);
742 	P_GET_STR(Name);
743 	P_GET_SELF;
744 	Self->SetDecorateFlag(Name, Value);
745 }
746