]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/clientkill.qc
Apply a standard alphabetical sort order to the server side includes and use constant...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / clientkill.qc
1 #include "clientkill.qh"
2
3 #include <common/mapobjects/triggers.qh>
4 #include <common/notifications/all.qh>
5 #include <common/stats.qh>
6 #include <common/stats.qh>
7 #include <common/vehicles/sv_vehicles.qh>
8 #include <common/weapons/_all.qh>
9 #include <server/client.qh>
10 #include <server/damage.qh>
11 #include <server/mutators/_mod.qh>
12 #include <server/player.qh>
13 #include <server/teamplay.qh>
14
15 void ClientKill_Now_TeamChange(entity this)
16 {
17         if (this.killindicator_teamchange == -1)
18         {
19                 TeamBalance_JoinBestTeam(this);
20         }
21         else if (this.killindicator_teamchange == -2)
22         {
23                 if (blockSpectators)
24                         Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
25                 PutObserverInServer(this);
26         }
27         else
28         {
29                 Player_SetTeamIndexChecked(this, Team_TeamToIndex(
30                         this.killindicator_teamchange));
31         }
32         this.killindicator_teamchange = 0;
33 }
34
35 void ClientKill_Now(entity this)
36 {
37         if (this.vehicle)
38         {
39                 vehicles_exit(this.vehicle, VHEF_RELEASE);
40                 if (!this.killindicator_teamchange)
41                 {
42                         this.vehicle_health = -1;
43                         Damage(this, this, this, 1 , DEATH_KILL.m_id, DMG_NOWEP, this.origin, '0 0 0');
44                 }
45         }
46
47         if (this.killindicator && !wasfreed(this.killindicator))
48                 delete(this.killindicator);
49
50         this.killindicator = NULL;
51
52         if (this.killindicator_teamchange)
53                 ClientKill_Now_TeamChange(this);
54
55         if (!IS_SPEC(this) && !IS_OBSERVER(this) && MUTATOR_CALLHOOK(ClientKill_Now, this) == false)
56         {
57                 Damage(this, this, this, 100000, DEATH_KILL.m_id, DMG_NOWEP, this.origin, '0 0 0');
58         }
59
60         // now I am sure the player IS dead
61 }
62 void KillIndicator_Think(entity this)
63 {
64         if (game_stopped || (this.owner.alpha < 0 && !this.owner.vehicle))
65         {
66                 this.owner.killindicator = NULL;
67                 delete(this);
68                 return;
69         }
70
71         if (this.cnt <= 0)
72         {
73                 ClientKill_Now(this.owner);
74                 return;
75         }
76
77         // count == 1 means that it's silent
78         if (this.count != 1)
79         {
80                 if (this.cnt <= 10)
81                         setmodel(this, MDL_NUM(this.cnt));
82                 if (IS_REAL_CLIENT(this.owner))
83                 {
84                         if (this.cnt <= 10)
85                                 Send_Notification(NOTIF_ONE, this.owner, MSG_ANNCE, Announcer_PickNumber(CNT_KILL, this.cnt));
86                 }
87         }
88         this.nextthink = time + 1;
89         this.cnt -= 1;
90 }
91
92 .float lip;
93 float clientkilltime;
94 .float clientkill_nexttime;
95 void ClientKill_TeamChange(entity this, float targetteam) // 0 = don't change, -1 = auto, -2 = spec
96 {
97         if (game_stopped)
98                 return;
99
100         float killtime = autocvar_g_balance_kill_delay;
101
102         if (MUTATOR_CALLHOOK(ClientKill, this, killtime))
103                 return;
104         killtime = M_ARGV(1, float);
105
106         this.killindicator_teamchange = targetteam;
107
108         // this.killindicator.count == 1 means that the kill indicator was spawned by ClientKill_Silent
109         if(killtime <= 0 && this.killindicator && this.killindicator.count == 1)
110         {
111                 ClientKill_Now(this); // allow instant kill in this case
112                 return;
113         }
114
115         if (!this.killindicator)
116         {
117                 if (!IS_DEAD(this))
118                 {
119                         killtime = max(killtime, this.clientkill_nexttime - time);
120                         this.clientkill_nexttime = time + killtime + autocvar_g_balance_kill_antispam;
121                 }
122
123                 if (killtime <= 0 || !IS_PLAYER(this) || IS_DEAD(this))
124                 {
125                         ClientKill_Now(this);
126                 }
127                 else
128                 {
129                         float starttime = max(time, clientkilltime);
130
131                         this.killindicator = spawn();
132                         this.killindicator.owner = this;
133                         this.killindicator.scale = 0.5;
134                         setattachment(this.killindicator, this, "");
135                         setorigin(this.killindicator, '0 0 52');
136                         setthink(this.killindicator, KillIndicator_Think);
137                         this.killindicator.nextthink = starttime + (this.lip) * 0.05;
138                         clientkilltime = max(clientkilltime, this.killindicator.nextthink + 0.05);
139                         this.killindicator.cnt = ceil(killtime);
140                         this.killindicator.count = bound(0, ceil(killtime), 10);
141                         //sprint(this, strcat("^1You'll be dead in ", ftos(this.killindicator.cnt), " seconds\n"));
142
143                         IL_EACH(g_clones, it.enemy == this && !(it.effects & CSQCMODEL_EF_RESPAWNGHOST) && !it.killindicator,
144                         {
145                                 it.killindicator = spawn();
146                                 it.killindicator.owner = it;
147                                 it.killindicator.scale = 0.5;
148                                 setattachment(it.killindicator, it, "");
149                                 setorigin(it.killindicator, '0 0 52');
150                                 setthink(it.killindicator, KillIndicator_Think);
151                                 it.killindicator.nextthink = starttime + (it.lip) * 0.05;
152                                 //clientkilltime = max(clientkilltime, it.killindicator.nextthink + 0.05);
153                                 it.killindicator.cnt = ceil(killtime);
154                         });
155                         this.lip = 0;
156                 }
157         }
158         if (this.killindicator)
159         {
160                 Notification notif;
161                 if (targetteam == 0) // just die
162                 {
163                         this.killindicator.colormod = '0 0 0';
164                         notif = CENTER_TEAMCHANGE_SUICIDE;
165                 }
166                 else if (targetteam == -1) // auto
167                 {
168                         this.killindicator.colormod = '0 1 0';
169                         notif = CENTER_TEAMCHANGE_AUTO;
170                 }
171                 else if (targetteam == -2) // spectate
172                 {
173                         this.killindicator.colormod = '0.5 0.5 0.5';
174                         notif = CENTER_TEAMCHANGE_SPECTATE;
175                 }
176                 else
177                 {
178                         this.killindicator.colormod = Team_ColorRGB(targetteam);
179                         notif = APP_TEAM_NUM(targetteam, CENTER_TEAMCHANGE);
180                 }
181                 if (IS_REAL_CLIENT(this) && this.killindicator.cnt > 0)
182                         Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, notif, this.killindicator.cnt);
183         }
184
185 }
186
187 void ClientKill_Silent(entity this, float _delay)
188 {
189         this.killindicator = spawn();
190         this.killindicator.owner = this;
191         setthink(this.killindicator, KillIndicator_Think);
192         this.killindicator.nextthink = time + (this.lip) * 0.05;
193         this.killindicator.cnt = ceil(_delay);
194         this.killindicator.count = 1; // this is used to indicate that it should be silent
195         this.lip = 0;
196 }
197
198 // Called when a client types 'kill' in the console
199 void ClientKill(entity this)
200 {
201         if (game_stopped || this.player_blocked || STAT(FROZEN, this))
202                 return;
203
204         ClientKill_TeamChange(this, 0);
205 }