]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/w_rpc.qc
Merge branch 'master' into Mario/overkill
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / w_rpc.qc
1 #ifdef REGISTER_WEAPON
2 REGISTER_WEAPON(
3 /* WEP_##id      */ RPC,
4 /* function      */ w_rpc,
5 /* ammotype      */ IT_ROCKETS,
6 /* impulse       */ 7,
7 /* flags         */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_SUPERWEAPON,
8 /* rating        */ BOT_PICKUP_RATING_HIGH,
9 /* model         */ "ok_rl",
10 /* shortname */ "rpc",
11 /* fullname      */ _("Rocket Propelled Chainsaw")
12 );
13 #else
14 #ifdef SVQC
15
16 void W_RPC_Explode()
17 {
18         self.event_damage = func_null;
19         self.takedamage = DAMAGE_NO;
20
21         RadiusDamage (self, self.realowner, autocvar_g_balance_rpc_damage, autocvar_g_balance_rpc_edgedamage, autocvar_g_balance_rpc_radius, world, autocvar_g_balance_rpc_force, self.projectiledeathtype, other);
22
23         remove (self);
24 }
25
26 void W_RPC_Touch (void)
27 {
28         if(WarpZone_Projectile_Touch())
29                 if(wasfreed(self))
30                         return;
31
32         //if(other.solid != SOLID_BSP)
33         //        return;
34
35         W_RPC_Explode();
36 }
37
38 void W_RPC_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
39 {
40         if (self.health <= 0)
41                 return;
42
43         if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
44                 return; // g_projectiles_damage says to halt
45
46         self.health = self.health - damage;
47
48         if (self.health <= 0)
49                 W_PrepareExplosionByDamage(attacker, W_RPC_Explode);
50 }
51
52 void W_RPC_Think()
53 {
54         if(self.cnt <= time)
55         {
56                 remove(self);
57                 return;
58         }
59
60         self.cnt = vlen(self.velocity);
61         self.wait = self.cnt * sys_frametime;
62         self.pos1 = normalize(self.velocity);
63
64         tracebox(self.origin, self.mins, self.maxs, self.origin + self.pos1 * (2 * self.wait), MOVE_NORMAL, self);
65         if(IS_PLAYER(trace_ent))
66                 Damage (trace_ent, self, self.realowner, autocvar_g_balance_rpc_damage2, self.projectiledeathtype, self.origin, normalize(self.origin - other.origin) * autocvar_g_balance_rpc_force);
67
68         self.velocity = self.pos1 * (self.cnt + (autocvar_g_balance_rpc_speedaccel * sys_frametime));
69
70         UpdateCSQCProjectile(self);
71         self.nextthink = time;
72 }
73
74 void W_RPC_Attack (void)
75 {
76         entity missile = spawn(); //WarpZone_RefSys_SpawnSameRefSys(self);
77         entity flash = spawn ();
78
79         W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_rpc_ammo, autocvar_g_balance_rpc_reload_ammo);
80         W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, autocvar_g_balance_rpc_damage);
81         pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
82         PROJECTILE_MAKETRIGGER(missile);
83
84         missile.owner = missile.realowner = self;
85         missile.bot_dodge = TRUE;
86         missile.bot_dodgerating = autocvar_g_balance_rpc_damage * 2;
87
88         missile.takedamage = DAMAGE_YES;
89         missile.damageforcescale = autocvar_g_balance_rpc_damageforcescale;
90         missile.health = autocvar_g_balance_rpc_health;
91         missile.event_damage = W_RPC_Damage;
92         missile.damagedbycontents = TRUE;
93         missile.movetype = MOVETYPE_FLY;
94
95         missile.projectiledeathtype = WEP_RPC;
96         setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
97
98         setorigin (missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point
99         W_SetupProjectileVelocity(missile, autocvar_g_balance_rpc_speed, 0);
100
101         missile.touch = W_RPC_Touch;
102
103         missile.think = W_RPC_Think;
104         //missile.think = SUB_Remove;
105         missile.cnt = time + autocvar_g_balance_rpc_lifetime;
106         missile.nextthink = time;
107         //missile.nextthink = time + autocvar_g_balance_rpc_lifetime;
108         missile.flags = FL_PROJECTILE;
109
110         CSQCProjectile(missile, TRUE, PROJECTILE_RPC, FALSE);
111         //CSQCProjectile(missile, TRUE, PROJECTILE_ROCKET, FALSE);
112
113         setmodel(flash, "models/flash.md3"); // precision set below
114         SUB_SetFade (flash, time, 0.1);
115         flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
116         W_AttachToShotorg(flash, '5 0 0');
117         missile.pos1 = missile.velocity;
118
119         other = missile; MUTATOR_CALLHOOK(EditProjectile);
120         //BITXOR_ASSIGN(self.weaponentity.effects, EF_RESTARTANIM_BIT);
121 }
122
123 void spawnfunc_weapon_rpc()
124 {
125         weapon_defaultspawnfunc(WEP_RPC);
126 }
127
128 float w_rpc(float req)
129 {
130         float ammo_amount = FALSE;
131
132         if (req == WR_AIM)
133         {
134                 self.BUTTON_ATCK = bot_aim(autocvar_g_balance_rpc_speed, 0, autocvar_g_balance_rpc_lifetime, FALSE);
135         }
136         else if (req == WR_THINK)
137         {
138                 if(autocvar_g_balance_rpc_reload_ammo && self.clip_load < autocvar_g_balance_rpc_ammo)
139                         weapon_action(self.weapon, WR_RELOAD);
140                 else
141                 {
142                         if (self.BUTTON_ATCK)
143                         {
144                                 if(weapon_prepareattack(0, autocvar_g_balance_rpc_refire))
145                                 {
146                                         W_RPC_Attack();
147                                         weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_rpc_animtime, w_ready);
148                                 }
149                         }
150
151                         if (self.BUTTON_ATCK2)
152                         {
153                                 // to-do
154                         }
155                 }
156         }
157         else if (req == WR_PRECACHE)
158         {
159                 precache_model ("models/flash.md3");
160                 /*precache_model ("models/weapons/g_rl.md3");
161                 precache_model ("models/weapons/v_rl.md3");
162                 precache_model ("models/weapons/h_rl.iqm");*/
163                 precache_sound ("weapons/rocket_det.wav");
164                 precache_sound ("weapons/rocket_fire.wav");
165                 precache_sound ("weapons/rocket_mode.wav");
166         }
167         else if (req == WR_SETUP)
168         {
169                 weapon_setup(WEP_RPC);
170                 self.current_ammo = ammo_rockets;
171         }
172         else if (req == WR_CHECKAMMO1)
173         {
174                 if(autocvar_g_balance_rpc_reload_ammo)
175                 {
176                         if(self.ammo_rockets < autocvar_g_balance_rpc_ammo && self.(weapon_load[WEP_RPC]) < autocvar_g_balance_rpc_ammo)
177                                 ammo_amount = TRUE;
178                 }
179                 else if(self.ammo_rockets < autocvar_g_balance_rpc_ammo)
180                         ammo_amount = TRUE;
181
182                 return !ammo_amount;
183         }
184         else if (req == WR_CHECKAMMO2)
185                 return FALSE;
186         else if (req == WR_RESETPLAYER)
187         {
188         }
189         else if (req == WR_RELOAD)
190         {
191                 W_Reload(autocvar_g_balance_rpc_ammo, autocvar_g_balance_rpc_reload_ammo, autocvar_g_balance_rpc_reload_time, "weapons/reload.wav");
192         }
193         else if (req == WR_SUICIDEMESSAGE)
194         {
195                 return WEAPON_RPC_SUICIDE;
196         }
197         else if (req == WR_KILLMESSAGE)
198         {
199                 if(w_deathtype & HITTYPE_SECONDARY)
200                         return WEAPON_LASER_MURDER;
201                 else if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH))
202                         return WEAPON_RPC_MURDER_SPLASH;
203                 else
204                         return WEAPON_RPC_MURDER_DIRECT;
205         }
206         return TRUE;
207 }
208 #endif
209
210 #ifdef CSQC
211 float w_rpc(float req)
212 {
213         if(req == WR_IMPACTEFFECT)
214         {
215                 vector org2;
216                 org2 = w_org + w_backoff * 12;
217                 pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
218                 if(!w_issilent)
219                         sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
220         }
221         else if(req == WR_PRECACHE)
222         {
223                 precache_sound("weapons/rocket_impact.wav");
224         }
225         return TRUE;
226 }
227 #endif
228 #endif