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