1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
global function GamemodeSpeedball_Init
struct {
entity flagBase
entity flag
entity flagCarrier
} file
void function GamemodeSpeedball_Init()
{
PrecacheModel( CTF_FLAG_MODEL )
PrecacheModel( CTF_FLAG_BASE_MODEL )
// gamemode settings
SetRoundBased( true )
SetRespawnsEnabled( false )
SetShouldUseRoundWinningKillReplay( true )
Riff_ForceTitanAvailability( eTitanAvailability.Never )
Riff_ForceSetEliminationMode( eEliminationMode.Pilots )
AddSpawnCallbackEditorClass( "script_ref", "info_speedball_flag", CreateFlag )
AddCallback_GameStateEnter( eGameState.Playing, ResetFlag )
AddCallback_OnTouchHealthKit( "item_flag", OnFlagCollected )
AddCallback_OnPlayerKilled( OnPlayerKilled )
SetTimeoutWinnerDecisionFunc( TimeoutCheckFlagHolder )
ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, NOINTRO_INTRO_LENGTH )
}
void function CreateFlag( entity flagSpawn )
{
entity flagBase = CreatePropDynamic( CTF_FLAG_BASE_MODEL, flagSpawn.GetOrigin(), flagSpawn.GetAngles() )
entity flag = CreateEntity( "item_flag" )
flag.SetValueForModelKey( CTF_FLAG_MODEL )
flag.MarkAsNonMovingAttachment()
DispatchSpawn( flag )
flag.SetModel( CTF_FLAG_MODEL )
flag.SetOrigin( flagBase.GetOrigin() + < 0, 0, flagBase.GetBoundingMaxs().z + 1 > )
flag.SetVelocity( < 0, 0, 1 > )
file.flag = flag
file.flagBase = flagBase
}
bool function OnFlagCollected( entity player, entity flag )
{
if ( !IsAlive( player ) || flag.GetParent() != null || player.IsTitan() || player.IsPhaseShifted() )
return false
GiveFlag( player )
return false // so flag ent doesn't despawn
}
void function OnPlayerKilled( entity victim, entity attacker, var damageInfo )
{
if ( file.flagCarrier == victim )
DropFlag()
if ( victim.IsPlayer() && GetGameState() == eGameState.Playing )
if ( GetPlayerArrayOfTeam_Alive( victim.GetTeam() ).len() == 1 )
foreach ( entity player in GetPlayerArray() )
Remote_CallFunction_NonReplay( player, "ServerCallback_SPEEDBALL_LastPlayer", player.GetTeam() != victim.GetTeam() )
}
void function GiveFlag( entity player )
{
file.flag.SetParent( player, "FLAG" )
file.flagCarrier = player
SetGlobalNetEnt( "flagCarrier", player )
thread DropFlagIfPhased( player )
EmitSoundOnEntityOnlyToPlayer( player, player, "UI_CTF_1P_GrabFlag" )
foreach ( entity otherPlayer in GetPlayerArray() )
{
MessageToPlayer( otherPlayer, eEventNotifications.SPEEDBALL_FlagPickedUp, player )
if ( otherPlayer.GetTeam() == player.GetTeam() )
EmitSoundOnEntityToTeamExceptPlayer( file.flag, "UI_CTF_3P_TeamGrabFlag", player.GetTeam(), player )
}
}
void function DropFlagIfPhased( entity player )
{
player.EndSignal( "StartPhaseShift" )
OnThreadEnd( function() : ( player )
{
if ( file.flag.GetParent() == player )
DropFlag()
})
while( file.flag.GetParent() == player )
WaitFrame()
}
void function DropFlag()
{
file.flag.ClearParent()
file.flag.SetAngles( < 0, 0, 0 > )
SetGlobalNetEnt( "flagCarrier", file.flag )
EmitSoundOnEntityOnlyToPlayer( file.flagCarrier, file.flagCarrier, "UI_CTF_1P_FlagDrop" )
foreach ( entity player in GetPlayerArray() )
MessageToPlayer( player, eEventNotifications.SPEEDBALL_FlagDropped, file.flagCarrier )
file.flagCarrier = null
}
void function ResetFlag()
{
file.flag.ClearParent()
file.flag.SetAngles( < 0, 0, 0 > )
file.flag.SetVelocity( < 0, 0, 1 > ) // hack: for some reason flag won't have gravity if i don't do this
file.flag.SetOrigin( file.flagBase.GetOrigin() + < 0, 0, file.flagBase.GetBoundingMaxs().z * 2 > )
file.flagCarrier = null
SetGlobalNetEnt( "flagCarrier", file.flag )
}
int function TimeoutCheckFlagHolder()
{
if ( file.flagCarrier == null )
return TEAM_UNASSIGNED
return file.flagCarrier.GetTeam()
}
|