Merge branch 'master' into Mario/vaporizer_damage
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_campcheck.qc
1 #include "../_all.qh"
2
3 #include "mutator.qh"
4
5 #include "../campaign.qh"
6
7 .float campcheck_nextcheck;
8 .float campcheck_traveled_distance;
9
10 MUTATOR_HOOKFUNCTION(campcheck_PlayerDies)
11 {
12         Kill_Notification(NOTIF_ONE, self, MSG_CENTER_CPID, CPID_CAMPCHECK);
13
14         return false;
15 }
16
17 MUTATOR_HOOKFUNCTION(campcheck_PlayerDamage)
18 {
19         if(IS_PLAYER(frag_target))
20         if(IS_PLAYER(frag_attacker))
21         if(frag_attacker != frag_target)
22         {
23                 frag_target.campcheck_traveled_distance = autocvar_g_campcheck_distance;
24                 frag_attacker.campcheck_traveled_distance = autocvar_g_campcheck_distance;
25         }
26
27         return false;
28 }
29
30 MUTATOR_HOOKFUNCTION(campcheck_PlayerThink)
31 {
32         if(!gameover)
33         if(!warmup_stage) // don't consider it camping during warmup?
34         if(time >= game_starttime)
35         if(IS_PLAYER(self))
36         if(IS_REAL_CLIENT(self)) // bots may camp, but that's no reason to constantly kill them
37         if(self.deadflag == DEAD_NO)
38         if(!self.frozen)
39         if(!self.BUTTON_CHAT)
40         if(autocvar_g_campcheck_interval)
41         {
42                 vector dist;
43
44                 // calculate player movement (in 2 dimensions only, so jumping on one spot doesn't count as movement)
45                 dist = self.prevorigin - self.origin;
46                 dist.z = 0;
47                 self.campcheck_traveled_distance += fabs(vlen(dist));
48
49                 if((autocvar_g_campaign && !campaign_bots_may_start) || (time < game_starttime) || (round_handler_IsActive() && !round_handler_IsRoundStarted()))
50                 {
51                         self.campcheck_nextcheck = time + autocvar_g_campcheck_interval * 2;
52                         self.campcheck_traveled_distance = 0;
53                 }
54
55                 if(time > self.campcheck_nextcheck)
56                 {
57                         if(self.campcheck_traveled_distance < autocvar_g_campcheck_distance)
58                         {
59                                 Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_CAMPCHECK);
60                                 if(self.vehicle)
61                                         Damage(self.vehicle, self, self, autocvar_g_campcheck_damage * 2, DEATH_CAMP, self.vehicle.origin, '0 0 0');
62                                 else
63                                         Damage(self, self, self, bound(0, autocvar_g_campcheck_damage, self.health + self.armorvalue * autocvar_g_balance_armor_blockpercent + 5), DEATH_CAMP, self.origin, '0 0 0');
64                         }
65                         self.campcheck_nextcheck = time + autocvar_g_campcheck_interval;
66                         self.campcheck_traveled_distance = 0;
67                 }
68
69                 return false;
70         }
71
72         self.campcheck_nextcheck = time + autocvar_g_campcheck_interval; // one of the above checks failed, so keep the timer up to date
73         return false;
74 }
75
76 MUTATOR_HOOKFUNCTION(campcheck_PlayerSpawn)
77 {
78         self.campcheck_nextcheck = time + autocvar_g_campcheck_interval * 2;
79         self.campcheck_traveled_distance = 0;
80
81         return false;
82 }
83
84 MUTATOR_HOOKFUNCTION(campcheck_BuildMutatorsString)
85 {
86         ret_string = strcat(ret_string, ":CampCheck");
87         return false;
88 }
89
90 MUTATOR_DEFINITION(mutator_campcheck)
91 {
92         MUTATOR_HOOK(PlayerDies, campcheck_PlayerDies, CBC_ORDER_ANY);
93         MUTATOR_HOOK(PlayerDamage_Calculate, campcheck_PlayerDamage, CBC_ORDER_ANY);
94         MUTATOR_HOOK(PlayerPreThink, campcheck_PlayerThink, CBC_ORDER_ANY);
95         MUTATOR_HOOK(PlayerSpawn, campcheck_PlayerSpawn, CBC_ORDER_ANY);
96         MUTATOR_HOOK(BuildMutatorsString, campcheck_BuildMutatorsString, CBC_ORDER_ANY);
97
98         return false;
99 }