1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** $Id: p_player.cpp 4316 2010-07-01 12:36:28Z 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 // HEADER FILES ------------------------------------------------------------
27
28 #include "gamedefs.h"
29 #include "network.h"
30 #include "sv_local.h"
31 #include "cl_local.h"
32
33 // MACROS ------------------------------------------------------------------
34
35 // TYPES -------------------------------------------------------------------
36
37 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
38
39 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
40
41 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
42
43 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
44
45 // PUBLIC DATA DEFINITIONS -------------------------------------------------
46
47 // PRIVATE DATA DEFINITIONS ------------------------------------------------
48
49 IMPLEMENT_CLASS(V, BasePlayer)
50
51 static VCvarF notify_time("notify_time", "5", CVAR_Archive);
52 static VCvarF centre_msg_time("centre_message_time", "7", CVAR_Archive);
53 static VCvarI msg_echo("msg_echo", "1", CVAR_Archive);
54 static VCvarI font_colour("font_colour", "11", CVAR_Archive);
55 static VCvarI font_colour2("font_colour2", "11", CVAR_Archive);
56
57 // CODE --------------------------------------------------------------------
58
59 //==========================================================================
60 //
61 // VBasePlayer::ExecuteNetMethod
62 //
63 //==========================================================================
64
ExecuteNetMethod(VMethod * Func)65 bool VBasePlayer::ExecuteNetMethod(VMethod* Func)
66 {
67 guard(VBasePlayer::ExecuteNetMethod);
68 if (GDemoRecordingContext)
69 {
70 // Find initial version of the method.
71 VMethod* Base = Func;
72 while (Base->SuperMethod)
73 {
74 Base = Base->SuperMethod;
75 }
76 // Execute it's replication condition method.
77 check(Base->ReplCond);
78 P_PASS_REF(this);
79 vuint32 SavedFlags = PlayerFlags;
80 PlayerFlags &= ~VBasePlayer::PF_IsClient;
81 bool ShouldSend = false;
82 if (VObject::ExecuteFunction(Base->ReplCond).i)
83 {
84 ShouldSend = true;
85 }
86 PlayerFlags = SavedFlags;
87
88 if (ShouldSend)
89 {
90 // Replication condition is true, the method must be replicated.
91 GDemoRecordingContext->ClientConnections[0]->Channels[
92 CHANIDX_Player]->SendRpc(Func, this);
93 }
94 }
95
96 #ifdef CLIENT
97 if (GGameInfo->NetMode == NM_TitleMap ||
98 GGameInfo->NetMode == NM_Standalone ||
99 (GGameInfo->NetMode == NM_ListenServer && this == cl))
100 {
101 return false;
102 }
103 #endif
104
105 // Find initial version of the method.
106 VMethod* Base = Func;
107 while (Base->SuperMethod)
108 {
109 Base = Base->SuperMethod;
110 }
111 // Execute it's replication condition method.
112 check(Base->ReplCond);
113 P_PASS_REF(this);
114 if (!VObject::ExecuteFunction(Base->ReplCond).i)
115 {
116 return false;
117 }
118
119 if (Net)
120 {
121 // Replication condition is true, the method must be replicated.
122 Net->Channels[CHANIDX_Player]->SendRpc(Func, this);
123 }
124
125 // Clean up parameters
126 guard(CleanUp);
127 VStack* Param = pr_stackPtr - Func->ParamsSize + 1; // Skip self
128 for (int i = 0; i < Func->NumParams; i++)
129 {
130 switch (Func->ParamTypes[i].Type)
131 {
132 case TYPE_Int:
133 case TYPE_Byte:
134 case TYPE_Bool:
135 case TYPE_Float:
136 case TYPE_Name:
137 case TYPE_Pointer:
138 case TYPE_Reference:
139 case TYPE_Class:
140 case TYPE_State:
141 Param++;
142 break;
143 case TYPE_String:
144 ((VStr*)&Param->p)->Clean();
145 Param++;
146 break;
147 case TYPE_Vector:
148 Param += 3;
149 break;
150 default:
151 Sys_Error("Bad method argument type %d", Func->ParamTypes[i].Type);
152 }
153 if (Func->ParamFlags[i] & FPARM_Optional)
154 {
155 Param++;
156 }
157 }
158 pr_stackPtr -= Func->ParamsSize;
159 unguard;
160
161 // Push null return value
162 guard(RetVal);
163 switch (Func->ReturnType.Type)
164 {
165 case TYPE_Void:
166 break;
167 case TYPE_Int:
168 case TYPE_Byte:
169 case TYPE_Bool:
170 case TYPE_Name:
171 PR_Push(0);
172 break;
173 case TYPE_Float:
174 PR_Pushf(0);
175 break;
176 case TYPE_String:
177 PR_PushStr(VStr());
178 break;
179 case TYPE_Pointer:
180 case TYPE_Reference:
181 case TYPE_Class:
182 case TYPE_State:
183 PR_PushPtr(NULL);
184 break;
185 case TYPE_Vector:
186 PR_Pushf(0);
187 PR_Pushf(0);
188 PR_Pushf(0);
189 break;
190 default:
191 Sys_Error("Bad return value type");
192 }
193 unguard;
194
195 // It's been handled here.
196 return true;
197 unguard;
198 }
199
200 //==========================================================================
201 //
202 // VBasePlayer::SpawnClient
203 //
204 //==========================================================================
205
SpawnClient()206 void VBasePlayer::SpawnClient()
207 {
208 guard(VBasePlayer::SpawnClient);
209 if (!sv_loading)
210 {
211 if (PlayerFlags & PF_Spawned)
212 {
213 GCon->Log(NAME_Dev, "Already spawned");
214 }
215 if (MO)
216 {
217 GCon->Log(NAME_Dev, "Mobj already spawned");
218 }
219 eventSpawnClient();
220 for (int i = 0; i < Level->XLevel->ActiveSequences.Num(); i++)
221 {
222 eventClientStartSequence(
223 Level->XLevel->ActiveSequences[i].Origin,
224 Level->XLevel->ActiveSequences[i].OriginId,
225 Level->XLevel->ActiveSequences[i].Name,
226 Level->XLevel->ActiveSequences[i].ModeNum);
227 for (int j = 0; j < Level->XLevel->ActiveSequences[i].Choices.Num(); j++)
228 {
229 eventClientAddSequenceChoice(
230 Level->XLevel->ActiveSequences[i].OriginId,
231 Level->XLevel->ActiveSequences[i].Choices[j]);
232 }
233 }
234 }
235 else
236 {
237 if (!MO)
238 {
239 Host_Error("Player without Mobj\n");
240 }
241 }
242
243 ViewAngles.roll = 0;
244 eventClientSetAngles(ViewAngles);
245 PlayerFlags &= ~PF_FixAngle;
246
247 PlayerFlags |= PF_Spawned;
248
249 if ((GGameInfo->NetMode == NM_TitleMap ||
250 GGameInfo->NetMode == NM_Standalone) && run_open_scripts)
251 {
252 // Start open scripts.
253 Level->XLevel->Acs->StartTypedACScripts(SCRIPT_Open, 0, 0, 0, NULL,
254 false, false);
255 }
256
257 if (!sv_loading)
258 {
259 Level->XLevel->Acs->StartTypedACScripts(SCRIPT_Enter, 0, 0, 0, MO,
260 true, false);
261 }
262 else if (sv_map_travel)
263 {
264 Level->XLevel->Acs->StartTypedACScripts(SCRIPT_Return, 0, 0, 0, MO,
265 true, false);
266 }
267
268 if (GGameInfo->NetMode < NM_DedicatedServer ||
269 svs.num_connected == sv_load_num_players)
270 {
271 sv_loading = false;
272 sv_map_travel = false;
273 }
274
275 // For single play, save immediately into the reborn slot
276 if (GGameInfo->NetMode < NM_DedicatedServer)
277 {
278 SV_SaveGame(SV_GetRebornSlot(), REBORN_DESCRIPTION);
279 }
280 unguard;
281 }
282
283 //==========================================================================
284 //
285 // VBasePlayer::Printf
286 //
287 //==========================================================================
288
Printf(const char * s,...)289 void VBasePlayer::Printf(const char *s, ...)
290 {
291 guard(VBasePlayer::Printf);
292 va_list v;
293 char buf[1024];
294
295 va_start(v, s);
296 vsprintf(buf, s, v);
297 va_end(v);
298
299 eventClientPrint(buf);
300 unguard;
301 }
302
303 //==========================================================================
304 //
305 // VBasePlayer::CentrePrintf
306 //
307 //==========================================================================
308
CentrePrintf(const char * s,...)309 void VBasePlayer::CentrePrintf(const char *s, ...)
310 {
311 guard(VBasePlayer::CentrePrintf);
312 va_list v;
313 char buf[1024];
314
315 va_start(v, s);
316 vsprintf(buf, s, v);
317 va_end(v);
318
319 eventClientCentrePrint(buf);
320 unguard;
321 }
322
323 //===========================================================================
324 //
325 // VBasePlayer::SetViewState
326 //
327 //===========================================================================
328
SetViewState(int position,VState * stnum)329 void VBasePlayer::SetViewState(int position, VState* stnum)
330 {
331 guard(VBasePlayer::SetViewState);
332 VViewState& VSt = ViewStates[position];
333 VState *state = stnum;
334 do
335 {
336 if (!state)
337 {
338 // Object removed itself.
339 VSt.State = NULL;
340 VSt.StateTime = -1;
341 break;
342 }
343 VSt.State = state;
344 VSt.StateTime = state->Time; // could be 0
345 if (state->Misc1)
346 {
347 VSt.SX = state->Misc1;
348 }
349 if (state->Misc2)
350 {
351 VSt.SY = state->Misc2;
352 }
353 // Call action routine.
354 if (state->Function)
355 {
356 Level->XLevel->CallingState = state;
357 P_PASS_REF(MO);
358 ExecuteFunction(state->Function);
359 if (!VSt.State)
360 {
361 break;
362 }
363 }
364 state = VSt.State->NextState;
365 }
366 while (!VSt.StateTime); // An initial state of 0 could cycle through.
367 unguard;
368 }
369
370 //==========================================================================
371 //
372 // VBasePlayer::AdvanceViewStates
373 //
374 //==========================================================================
375
AdvanceViewStates(float deltaTime)376 void VBasePlayer::AdvanceViewStates(float deltaTime)
377 {
378 for (int i = 0; i < NUMPSPRITES; i++)
379 {
380 VViewState& St = ViewStates[i];
381 // a null state means not active
382 if (St.State)
383 {
384 // drop tic count and possibly change state
385 // a -1 tic count never changes
386 if (St.StateTime != -1.0)
387 {
388 St.StateTime -= deltaTime;
389 if (St.StateTime <= 0.0)
390 {
391 St.StateTime = 0.0;
392 SetViewState(i, St.State->NextState);
393 }
394 }
395 }
396 }
397 }
398
399 //==========================================================================
400 //
401 // VBasePlayer::SetUserInfo
402 //
403 //==========================================================================
404
SetUserInfo(const VStr & info)405 void VBasePlayer::SetUserInfo(const VStr& info)
406 {
407 guard(VBasePlayer::SetUserInfo);
408 if (!sv_loading)
409 {
410 UserInfo = info;
411 ReadFromUserInfo();
412 }
413 unguard;
414 }
415
416 //==========================================================================
417 //
418 // VBasePlayer::ReadFromUserInfo
419 //
420 //==========================================================================
421
ReadFromUserInfo()422 void VBasePlayer::ReadFromUserInfo()
423 {
424 guard(VBasePlayer::ReadFromUserInfo);
425 if (!sv_loading)
426 {
427 BaseClass = atoi(*Info_ValueForKey(UserInfo, "class"));
428 }
429 PlayerName = Info_ValueForKey(UserInfo, "name");
430 Colour = M_ParseColour(Info_ValueForKey(UserInfo, "colour"));
431 eventUserinfoChanged();
432 unguard;
433 }
434
435 //==========================================================================
436 //
437 // VBasePlayer::DoClientStartSound
438 //
439 //==========================================================================
440
DoClientStartSound(int SoundId,TVec Org,int OriginId,int Channel,float Volume,float Attenuation,bool Loop)441 void VBasePlayer::DoClientStartSound(int SoundId, TVec Org, int OriginId,
442 int Channel, float Volume, float Attenuation, bool Loop)
443 {
444 #ifdef CLIENT
445 guard(VBasePlayer::DoClientStartSound);
446 GAudio->PlaySound(SoundId, Org, TVec(0, 0, 0), OriginId, Channel, Volume,
447 Attenuation, Loop);
448 unguard;
449 #endif
450 }
451
452 //==========================================================================
453 //
454 // VBasePlayer::DoClientStopSound
455 //
456 //==========================================================================
457
DoClientStopSound(int OriginId,int Channel)458 void VBasePlayer::DoClientStopSound(int OriginId, int Channel)
459 {
460 #ifdef CLIENT
461 guard(VBasePlayer::DoClientStopSound);
462 GAudio->StopSound(OriginId, Channel);
463 unguard;
464 #endif
465 }
466
467 //==========================================================================
468 //
469 // VBasePlayer::DoClientStartSequence
470 //
471 //==========================================================================
472
DoClientStartSequence(TVec Origin,int OriginId,VName Name,int ModeNum)473 void VBasePlayer::DoClientStartSequence(TVec Origin, int OriginId, VName Name,
474 int ModeNum)
475 {
476 #ifdef CLIENT
477 guard(VBasePlayer::DoClientStartSequence);
478 GAudio->StartSequence(OriginId, Origin, Name, ModeNum);
479 unguard;
480 #endif
481 }
482
483 //==========================================================================
484 //
485 // VBasePlayer::DoClientAddSequenceChoice
486 //
487 //==========================================================================
488
DoClientAddSequenceChoice(int OriginId,VName Choice)489 void VBasePlayer::DoClientAddSequenceChoice(int OriginId, VName Choice)
490 {
491 #ifdef CLIENT
492 guard(VBasePlayer::DoClientAddSequenceChoice);
493 GAudio->AddSeqChoice(OriginId, Choice);
494 unguard;
495 #endif
496 }
497
498 //==========================================================================
499 //
500 // VBasePlayer::DoClientStopSequence
501 //
502 //==========================================================================
503
DoClientStopSequence(int OriginId)504 void VBasePlayer::DoClientStopSequence(int OriginId)
505 {
506 #ifdef CLIENT
507 guard(VBasePlayer::DoClientStopSequence);
508 GAudio->StopSequence(OriginId);
509 unguard;
510 #endif
511 }
512
513 //==========================================================================
514 //
515 // VBasePlayer::DoClientPrint
516 //
517 //==========================================================================
518
DoClientPrint(VStr AStr)519 void VBasePlayer::DoClientPrint(VStr AStr)
520 {
521 guard(VBasePlayer::DoClientPrint);
522 VStr Str(AStr);
523
524 if (Str.IsEmpty())
525 {
526 return;
527 }
528
529 if (Str[0] == '$')
530 {
531 Str = GLanguage[*VStr(Str.ToLower(), 1, Str.Length() - 1)];
532 }
533
534 if (msg_echo)
535 {
536 GCon->Log(Str);
537 }
538
539 ClGame->eventAddNotifyMessage(Str);
540 unguard;
541 }
542
543 //==========================================================================
544 //
545 // VBasePlayer::DoClientCentrePrint
546 //
547 //==========================================================================
548
DoClientCentrePrint(VStr Str)549 void VBasePlayer::DoClientCentrePrint(VStr Str)
550 {
551 guard(VBasePlayer::DoClientCentrePrint);
552 VStr Msg(Str);
553
554 if (Msg.IsEmpty())
555 {
556 return;
557 }
558
559 if (Msg[0] == '$')
560 {
561 Msg = GLanguage[*VStr(Msg.ToLower(), 1, Msg.Length() - 1)];
562 }
563
564 if (msg_echo)
565 {
566 GCon->Log("<-------------------------------->");
567 GCon->Log(Msg);
568 GCon->Log("<-------------------------------->");
569 }
570
571 ClGame->eventAddCentreMessage(Msg);
572 unguard;
573 }
574
575 //==========================================================================
576 //
577 // VBasePlayer::DoClientSetAngles
578 //
579 //==========================================================================
580
DoClientSetAngles(TAVec Angles)581 void VBasePlayer::DoClientSetAngles(TAVec Angles)
582 {
583 guard(VBasePlayer::DoClientSetAngles);
584 ViewAngles = Angles;
585 ViewAngles.pitch = AngleMod180(ViewAngles.pitch);
586 unguard;
587 }
588
589 //==========================================================================
590 //
591 // VBasePlayer::DoClientIntermission
592 //
593 //==========================================================================
594
DoClientIntermission(VName NextMap)595 void VBasePlayer::DoClientIntermission(VName NextMap)
596 {
597 guard(VBasePlayer::DoClientIntermission);
598 im_t& im = ClGame->im;
599
600 im.Text.Clean();
601 im.IMFlags = 0;
602
603 const mapInfo_t& linfo = P_GetMapInfo(Level->XLevel->MapName);
604 im.LeaveMap = Level->XLevel->MapName;
605 im.LeaveCluster = linfo.Cluster;
606 im.LeaveName = linfo.GetName();
607 im.LeaveTitlePatch = linfo.TitlePatch;
608 im.ExitPic = linfo.ExitPic;
609 im.InterMusic = linfo.InterMusic;
610
611 const mapInfo_t& einfo = P_GetMapInfo(NextMap);
612 im.EnterMap = NextMap;
613 im.EnterCluster = einfo.Cluster;
614 im.EnterName = einfo.GetName();
615 im.EnterTitlePatch = einfo.TitlePatch;
616 im.EnterPic = einfo.EnterPic;
617
618 if (linfo.Cluster != einfo.Cluster)
619 {
620 if (einfo.Cluster)
621 {
622 const VClusterDef* CDef = P_GetClusterDef(einfo.Cluster);
623 if (CDef->EnterText.Length())
624 {
625 if (CDef->Flags & CLUSTERF_LookupEnterText)
626 {
627 im.Text = GLanguage[*CDef->EnterText];
628 }
629 else
630 {
631 im.Text = CDef->EnterText;
632 }
633 if (CDef->Flags & CLUSTERF_EnterTextIsLump)
634 {
635 im.IMFlags |= im_t::IMF_TextIsLump;
636 }
637 if (CDef->Flags & CLUSTERF_FinalePic)
638 {
639 im.TextFlat = NAME_None;
640 im.TextPic = CDef->Flat;
641 }
642 else
643 {
644 im.TextFlat = CDef->Flat;
645 im.TextPic = NAME_None;
646 }
647 im.TextMusic = CDef->Music;
648 im.TextCDTrack = CDef->CDTrack;
649 im.TextCDId = CDef->CDId;
650 }
651 }
652 if (im.Text.Length() == 0 && linfo.Cluster)
653 {
654 const VClusterDef* CDef = P_GetClusterDef(linfo.Cluster);
655 if (CDef->ExitText.Length())
656 {
657 if (CDef->Flags & CLUSTERF_LookupExitText)
658 {
659 im.Text = GLanguage[*CDef->ExitText];
660 }
661 else
662 {
663 im.Text = CDef->ExitText;
664 }
665 if (CDef->Flags & CLUSTERF_ExitTextIsLump)
666 {
667 im.IMFlags |= im_t::IMF_TextIsLump;
668 }
669 if (CDef->Flags & CLUSTERF_FinalePic)
670 {
671 im.TextFlat = NAME_None;
672 im.TextPic = CDef->Flat;
673 }
674 else
675 {
676 im.TextFlat = CDef->Flat;
677 im.TextPic = NAME_None;
678 }
679 im.TextMusic = CDef->Music;
680 im.TextCDTrack = CDef->CDTrack;
681 im.TextCDId = CDef->CDId;
682 }
683 }
684 }
685
686 ClGame->intermission = 1;
687 #ifdef CLIENT
688 AM_Stop();
689 GAudio->StopAllSequences();
690 #endif
691
692 ClGame->eventIintermissionStart();
693 unguard;
694 }
695
696 //==========================================================================
697 //
698 // VBasePlayer::DoClientPause
699 //
700 //==========================================================================
701
DoClientPause(bool Paused)702 void VBasePlayer::DoClientPause(bool Paused)
703 {
704 #ifdef CLIENT
705 guard(VBasePlayer::DoClientPause);
706 if (Paused)
707 {
708 GGameInfo->Flags |= VGameInfo::GIF_Paused;
709 GAudio->PauseSound();
710 }
711 else
712 {
713 GGameInfo->Flags &= ~VGameInfo::GIF_Paused;
714 GAudio->ResumeSound();
715 }
716 unguard;
717 #endif
718 }
719
720 //==========================================================================
721 //
722 // VBasePlayer::DoClientSkipIntermission
723 //
724 //==========================================================================
725
DoClientSkipIntermission()726 void VBasePlayer::DoClientSkipIntermission()
727 {
728 guard(VBasePlayer::DoClientSkipIntermission);
729 ClGame->ClientFlags |= VClientGameBase::CF_SkipIntermission;
730 unguard;
731 }
732
733 //==========================================================================
734 //
735 // VBasePlayer::DoClientFinale
736 //
737 //==========================================================================
738
DoClientFinale(VStr Type)739 void VBasePlayer::DoClientFinale(VStr Type)
740 {
741 guard(VBasePlayer::DoClientFinale);
742 ClGame->intermission = 2;
743 #ifdef CLIENT
744 AM_Stop();
745 #endif
746
747 ClGame->eventStartFinale(*Type);
748 unguard;
749 }
750
751 //==========================================================================
752 //
753 // VBasePlayer::DoClientChangeMusic
754 //
755 //==========================================================================
756
DoClientChangeMusic(VName Song,int CDTrack)757 void VBasePlayer::DoClientChangeMusic(VName Song, int CDTrack)
758 {
759 guard(VBasePlayer::DoClientChangeMusic);
760 Level->SongLump = Song;
761 Level->CDTrack = CDTrack;
762 #ifdef CLIENT
763 GAudio->MusicChanged();
764 #endif
765 unguard;
766 }
767
768 //==========================================================================
769 //
770 // VBasePlayer::DoClientSetServerInfo
771 //
772 //==========================================================================
773
DoClientSetServerInfo(VStr Key,VStr Value)774 void VBasePlayer::DoClientSetServerInfo(VStr Key, VStr Value)
775 {
776 guard(VBasePlayer::DoClientSetServerInfo);
777 Info_SetValueForKey(ClGame->serverinfo, Key, Value);
778 #ifdef CLIENT
779 CL_ReadFromServerInfo();
780 #endif
781 unguard;
782 }
783
784 //==========================================================================
785 //
786 // VBasePlayer::DoClientHudMessage
787 //
788 //==========================================================================
789
DoClientHudMessage(const VStr & Message,VName Font,int Type,int Id,int Colour,const VStr & ColourName,float x,float y,int HudWidth,int HudHeight,float HoldTime,float Time1,float Time2)790 void VBasePlayer::DoClientHudMessage(const VStr& Message, VName Font, int Type,
791 int Id, int Colour, const VStr& ColourName, float x, float y,
792 int HudWidth, int HudHeight, float HoldTime, float Time1, float Time2)
793 {
794 guard(VBasePlayer::DoClientHudMessage);
795 ClGame->eventAddHudMessage(Message, Font, Type, Id, Colour, ColourName,
796 x, y, HudWidth, HudHeight, HoldTime, Time1, Time2);
797 unguard;
798 }
799
800 //==========================================================================
801 //
802 // VBasePlayer::WriteViewData
803 //
804 //==========================================================================
805
WriteViewData()806 void VBasePlayer::WriteViewData()
807 {
808 guard(VBasePlayer::WriteViewData);
809 // Update bam_angles (after teleportation)
810 if (PlayerFlags & PF_FixAngle)
811 {
812 PlayerFlags &= ~PF_FixAngle;
813 eventClientSetAngles(ViewAngles);
814 }
815 unguard;
816 }
817
818 //==========================================================================
819 //
820 // COMMAND SetInfo
821 //
822 //==========================================================================
823
COMMAND(SetInfo)824 COMMAND(SetInfo)
825 {
826 guard(COMMAND SetInfo);
827 if (Source != SRC_Client)
828 {
829 GCon->Log("SetInfo is not valid from console");
830 return;
831 }
832
833 if (Args.Num() != 3)
834 {
835 return;
836 }
837
838 Info_SetValueForKey(Player->UserInfo, *Args[1], *Args[2]);
839 Player->ReadFromUserInfo();
840 unguard;
841 }
842
843 //==========================================================================
844 //
845 // Natives
846 //
847 //==========================================================================
848
IMPLEMENT_FUNCTION(VBasePlayer,cprint)849 IMPLEMENT_FUNCTION(VBasePlayer, cprint)
850 {
851 VStr msg = PF_FormatString();
852 P_GET_SELF;
853 Self->eventClientPrint(*msg);
854 }
855
IMPLEMENT_FUNCTION(VBasePlayer,centreprint)856 IMPLEMENT_FUNCTION(VBasePlayer, centreprint)
857 {
858 VStr msg = PF_FormatString();
859 P_GET_SELF;
860 Self->eventClientCentrePrint(*msg);
861 }
862
IMPLEMENT_FUNCTION(VBasePlayer,GetPlayerNum)863 IMPLEMENT_FUNCTION(VBasePlayer, GetPlayerNum)
864 {
865 P_GET_SELF;
866 RET_INT(SV_GetPlayerNum(Self));
867 }
868
IMPLEMENT_FUNCTION(VBasePlayer,ClearPlayer)869 IMPLEMENT_FUNCTION(VBasePlayer, ClearPlayer)
870 {
871 P_GET_SELF;
872
873 Self->PClass = 0;
874 Self->ForwardMove = 0;
875 Self->SideMove = 0;
876 Self->FlyMove = 0;
877 Self->Buttons = 0;
878 Self->Impulse = 0;
879 Self->MO = NULL;
880 Self->PlayerState = 0;
881 Self->ViewOrg = TVec(0, 0, 0);
882 Self->PlayerFlags &= ~VBasePlayer::PF_FixAngle;
883 Self->Health = 0;
884 Self->PlayerFlags &= ~VBasePlayer::PF_AttackDown;
885 Self->PlayerFlags &= ~VBasePlayer::PF_UseDown;
886 Self->PlayerFlags &= ~VBasePlayer::PF_AutomapRevealed;
887 Self->PlayerFlags &= ~VBasePlayer::PF_AutomapShowThings;
888 Self->ExtraLight = 0;
889 Self->FixedColourmap = 0;
890 Self->CShift = 0;
891 Self->PSpriteSY = 0;
892
893 vuint8* Def = Self->GetClass()->Defaults;
894 for (VField* F = Self->GetClass()->Fields; F; F = F->Next)
895 {
896 VField::CopyFieldValue(Def + F->Ofs, (vuint8*)Self + F->Ofs, F->Type);
897 }
898 }
899
IMPLEMENT_FUNCTION(VBasePlayer,SetViewState)900 IMPLEMENT_FUNCTION(VBasePlayer, SetViewState)
901 {
902 P_GET_PTR(VState, stnum);
903 P_GET_INT(position);
904 P_GET_SELF;
905 Self->SetViewState(position, stnum);
906 }
907
IMPLEMENT_FUNCTION(VBasePlayer,AdvanceViewStates)908 IMPLEMENT_FUNCTION(VBasePlayer, AdvanceViewStates)
909 {
910 P_GET_FLOAT(deltaTime);
911 P_GET_SELF;
912 Self->AdvanceViewStates(deltaTime);
913 }
914
IMPLEMENT_FUNCTION(VBasePlayer,DisconnectBot)915 IMPLEMENT_FUNCTION(VBasePlayer, DisconnectBot)
916 {
917 P_GET_SELF;
918 check(Self->PlayerFlags & PF_IsBot);
919 SV_DropClient(Self, false);
920 }
921
IMPLEMENT_FUNCTION(VBasePlayer,ClientStartSound)922 IMPLEMENT_FUNCTION(VBasePlayer, ClientStartSound)
923 {
924 P_GET_BOOL(Loop);
925 P_GET_FLOAT(Attenuation);
926 P_GET_FLOAT(Volume);
927 P_GET_INT(Channel);
928 P_GET_INT(OriginId);
929 P_GET_VEC(Org);
930 P_GET_INT(SoundId);
931 P_GET_SELF;
932 Self->DoClientStartSound(SoundId, Org, OriginId, Channel, Volume,
933 Attenuation, Loop);
934 }
935
IMPLEMENT_FUNCTION(VBasePlayer,ClientStopSound)936 IMPLEMENT_FUNCTION(VBasePlayer, ClientStopSound)
937 {
938 P_GET_INT(Channel);
939 P_GET_INT(OriginId);
940 P_GET_SELF;
941 Self->DoClientStopSound(OriginId, Channel);
942 }
943
IMPLEMENT_FUNCTION(VBasePlayer,ClientStartSequence)944 IMPLEMENT_FUNCTION(VBasePlayer, ClientStartSequence)
945 {
946 P_GET_INT(ModeNum);
947 P_GET_NAME(Name);
948 P_GET_INT(OriginId);
949 P_GET_VEC(Origin);
950 P_GET_SELF;
951 Self->DoClientStartSequence(Origin, OriginId, Name, ModeNum);
952 }
953
IMPLEMENT_FUNCTION(VBasePlayer,ClientAddSequenceChoice)954 IMPLEMENT_FUNCTION(VBasePlayer, ClientAddSequenceChoice)
955 {
956 P_GET_NAME(Choice);
957 P_GET_INT(OriginId);
958 P_GET_SELF;
959 Self->DoClientAddSequenceChoice(OriginId, Choice);
960 }
961
IMPLEMENT_FUNCTION(VBasePlayer,ClientStopSequence)962 IMPLEMENT_FUNCTION(VBasePlayer, ClientStopSequence)
963 {
964 P_GET_INT(OriginId);
965 P_GET_SELF;
966 Self->DoClientStopSequence(OriginId);
967 }
968
IMPLEMENT_FUNCTION(VBasePlayer,ClientPrint)969 IMPLEMENT_FUNCTION(VBasePlayer, ClientPrint)
970 {
971 P_GET_STR(Str);
972 P_GET_SELF;
973 Self->DoClientPrint(Str);
974 }
975
IMPLEMENT_FUNCTION(VBasePlayer,ClientCentrePrint)976 IMPLEMENT_FUNCTION(VBasePlayer, ClientCentrePrint)
977 {
978 P_GET_STR(Str);
979 P_GET_SELF;
980 Self->DoClientCentrePrint(Str);
981 }
982
IMPLEMENT_FUNCTION(VBasePlayer,ClientSetAngles)983 IMPLEMENT_FUNCTION(VBasePlayer, ClientSetAngles)
984 {
985 P_GET_AVEC(Angles);
986 P_GET_SELF;
987 Self->DoClientSetAngles(Angles);
988 }
989
IMPLEMENT_FUNCTION(VBasePlayer,ClientIntermission)990 IMPLEMENT_FUNCTION(VBasePlayer, ClientIntermission)
991 {
992 P_GET_NAME(NextMap);
993 P_GET_SELF;
994 Self->DoClientIntermission(NextMap);
995 }
996
IMPLEMENT_FUNCTION(VBasePlayer,ClientPause)997 IMPLEMENT_FUNCTION(VBasePlayer, ClientPause)
998 {
999 P_GET_BOOL(Paused);
1000 P_GET_SELF;
1001 Self->DoClientPause(Paused);
1002 }
1003
IMPLEMENT_FUNCTION(VBasePlayer,ClientSkipIntermission)1004 IMPLEMENT_FUNCTION(VBasePlayer, ClientSkipIntermission)
1005 {
1006 P_GET_SELF;
1007 Self->DoClientSkipIntermission();
1008 }
1009
IMPLEMENT_FUNCTION(VBasePlayer,ClientFinale)1010 IMPLEMENT_FUNCTION(VBasePlayer, ClientFinale)
1011 {
1012 P_GET_STR(Type);
1013 P_GET_SELF;
1014 Self->DoClientFinale(Type);
1015 }
1016
IMPLEMENT_FUNCTION(VBasePlayer,ClientChangeMusic)1017 IMPLEMENT_FUNCTION(VBasePlayer, ClientChangeMusic)
1018 {
1019 P_GET_INT(CDTrack);
1020 P_GET_NAME(Song);
1021 P_GET_SELF;
1022 Self->DoClientChangeMusic(Song, CDTrack);
1023 }
1024
IMPLEMENT_FUNCTION(VBasePlayer,ClientSetServerInfo)1025 IMPLEMENT_FUNCTION(VBasePlayer, ClientSetServerInfo)
1026 {
1027 P_GET_STR(Value);
1028 P_GET_STR(Key);
1029 P_GET_SELF;
1030 Self->DoClientSetServerInfo(Key, Value);
1031 }
1032
IMPLEMENT_FUNCTION(VBasePlayer,ClientHudMessage)1033 IMPLEMENT_FUNCTION(VBasePlayer, ClientHudMessage)
1034 {
1035 P_GET_FLOAT(Time2);
1036 P_GET_FLOAT(Time1);
1037 P_GET_FLOAT(HoldTime);
1038 P_GET_INT(HudHeight);
1039 P_GET_INT(HudWidth);
1040 P_GET_FLOAT(y);
1041 P_GET_FLOAT(x);
1042 P_GET_STR(ColourName);
1043 P_GET_INT(Colour);
1044 P_GET_INT(Id);
1045 P_GET_INT(Type);
1046 P_GET_NAME(Font);
1047 P_GET_STR(Message);
1048 P_GET_SELF;
1049 Self->DoClientHudMessage(Message, Font, Type, Id, Colour, ColourName,
1050 x, y, HudWidth, HudHeight, HoldTime, Time1, Time2);
1051 }
1052
IMPLEMENT_FUNCTION(VBasePlayer,ServerSetUserInfo)1053 IMPLEMENT_FUNCTION(VBasePlayer, ServerSetUserInfo)
1054 {
1055 P_GET_STR(Info);
1056 P_GET_SELF;
1057 Self->SetUserInfo(Info);
1058 }
1059