REGISTER_WEAPON(
/* WEP_##id */ DEVASTATOR,
/* function */ W_Devastator,
-/* ammotype */ IT_ROCKETS,
+/* ammotype */ ammo_rockets,
/* impulse */ 9,
/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
/* rating */ BOT_PICKUP_RATING_HIGH,
+/* color */ '1 1 0',
/* model */ "rl",
-/* shortname */ "devastator",
-/* fullname */ _("Devastator")
+/* crosshair */ "gfx/crosshairrocketlauncher 0.5875",
+/* refname */ "devastator",
+/* wepname */ _("Devastator")
);
-#define DEVASTATOR_SETTINGS(weapon) \
- WEP_ADD_CVAR(weapon, MO_NONE, ammo) \
- WEP_ADD_CVAR(weapon, MO_NONE, animtime) \
- WEP_ADD_CVAR(weapon, MO_NONE, damage) \
- WEP_ADD_CVAR(weapon, MO_NONE, damageforcescale) \
- WEP_ADD_CVAR(weapon, MO_NONE, detonatedelay) \
- WEP_ADD_CVAR(weapon, MO_NONE, edgedamage) \
- WEP_ADD_CVAR(weapon, MO_NONE, force) \
- WEP_ADD_CVAR(weapon, MO_NONE, guidedelay) \
- WEP_ADD_CVAR(weapon, MO_NONE, guidegoal) \
- WEP_ADD_CVAR(weapon, MO_NONE, guiderate) \
- WEP_ADD_CVAR(weapon, MO_NONE, guideratedelay) \
- WEP_ADD_CVAR(weapon, MO_NONE, guidestop) \
- WEP_ADD_CVAR(weapon, MO_NONE, health) \
- WEP_ADD_CVAR(weapon, MO_NONE, lifetime) \
- WEP_ADD_CVAR(weapon, MO_NONE, radius) \
- WEP_ADD_CVAR(weapon, MO_NONE, refire) \
- WEP_ADD_CVAR(weapon, MO_NONE, remote_damage) \
- WEP_ADD_CVAR(weapon, MO_NONE, remote_edgedamage) \
- WEP_ADD_CVAR(weapon, MO_NONE, remote_force) \
- WEP_ADD_CVAR(weapon, MO_NONE, remote_radius) \
- WEP_ADD_CVAR(weapon, MO_NONE, speed) \
- WEP_ADD_CVAR(weapon, MO_NONE, speedaccel) \
- WEP_ADD_CVAR(weapon, MO_NONE, speedstart) \
- WEP_ADD_PROP(weapon, reloading_ammo, reload_ammo) \
- WEP_ADD_PROP(weapon, reloading_time, reload_time) \
- WEP_ADD_PROP(weapon, switchdelay_raise, switchdelay_raise) \
- WEP_ADD_PROP(weapon, switchdelay_drop, switchdelay_drop)
+#define DEVASTATOR_SETTINGS(w_cvar,w_prop) DEVASTATOR_SETTINGS_LIST(w_cvar, w_prop, DEVASTATOR, devastator)
+#define DEVASTATOR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
+ w_cvar(id, sn, NONE, ammo) \
+ w_cvar(id, sn, NONE, animtime) \
+ w_cvar(id, sn, NONE, damage) \
+ w_cvar(id, sn, NONE, damageforcescale) \
+ w_cvar(id, sn, NONE, detonatedelay) \
+ w_cvar(id, sn, NONE, edgedamage) \
+ w_cvar(id, sn, NONE, force) \
+ w_cvar(id, sn, NONE, guidedelay) \
+ w_cvar(id, sn, NONE, guidegoal) \
+ w_cvar(id, sn, NONE, guiderate) \
+ w_cvar(id, sn, NONE, guideratedelay) \
+ w_cvar(id, sn, NONE, guidestop) \
+ w_cvar(id, sn, NONE, health) \
+ w_cvar(id, sn, NONE, lifetime) \
+ w_cvar(id, sn, NONE, radius) \
+ w_cvar(id, sn, NONE, refire) \
+ w_cvar(id, sn, NONE, remote_damage) \
+ w_cvar(id, sn, NONE, remote_edgedamage) \
+ w_cvar(id, sn, NONE, remote_force) \
+ w_cvar(id, sn, NONE, remote_radius) \
+ w_cvar(id, sn, NONE, speed) \
+ w_cvar(id, sn, NONE, speedaccel) \
+ w_cvar(id, sn, NONE, speedstart) \
+ w_prop(id, sn, float, reloading_ammo, reload_ammo) \
+ w_prop(id, sn, float, reloading_time, reload_time) \
+ w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \
+ w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \
+ w_prop(id, sn, string, weaponreplace, weaponreplace) \
+ w_prop(id, sn, float, weaponstart, weaponstart) \
+ w_prop(id, sn, float, weaponstartoverride, weaponstartoverride)
#ifdef SVQC
-DEVASTATOR_SETTINGS(devastator)
+DEVASTATOR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
.float rl_release;
.float rl_detonate_later;
#endif
if(other.takedamage == DAMAGE_AIM)
if(IS_PLAYER(other))
- if(IsDifferentTeam(self.realowner, other))
+ if(DIFF_TEAM(self.realowner, other))
if(other.deadflag == DEAD_NO)
if(IsFlying(other))
Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
if (self.realowner.weapon == WEP_DEVASTATOR)
{
- if(self.realowner.ammo_rockets < WEP_CVAR(devastator, ammo))
+ if(self.realowner.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
{
self.realowner.cnt = WEP_DEVASTATOR;
ATTACK_FINISHED(self.realowner) = time;
if (self.realowner.weapon == WEP_DEVASTATOR)
{
- if(self.realowner.ammo_rockets < WEP_CVAR(devastator, ammo))
+ if(self.realowner.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
{
self.realowner.cnt = WEP_DEVASTATOR;
ATTACK_FINISHED(self.realowner) = time;
if (self.realowner.weapon == WEP_DEVASTATOR)
{
if(self == self.realowner.lastrocket)
- if not(self.realowner.rl_release)
- if not(self.BUTTON_ATCK2)
+ if(!self.realowner.rl_release)
+ if(!self.BUTTON_ATCK2)
if(WEP_CVAR(devastator, guiderate))
if(time > self.pushltime)
if(self.realowner.deadflag == DEAD_NO)
entity missile;
entity flash;
- W_DecreaseAmmo(ammo_rockets, WEP_CVAR(devastator, ammo), WEP_CVAR(devastator, reload_ammo));
+ W_DecreaseAmmo(WEP_CVAR(devastator, ammo));
W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, WEP_CVAR(devastator, damage));
pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
setorigin (missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point
- W_SetupProjectileVelocity(missile, WEP_CVAR(devastator, speedstart), 0);
+ W_SetupProjVelocity_Basic(missile, WEP_CVAR(devastator, speedstart), 0);
missile.angles = vectoangles (missile.velocity);
missile.touch = W_Devastator_Touch;
float ammo_amount;
switch(req)
{
- case WR_AIM:
+ case WR_AIM: // WEAPONTODO: rewrite this, it's WAY too complicated for what it should be
{
// aim and decide to fire if appropriate
self.BUTTON_ATCK = bot_aim(WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), FALSE);
{
// decide whether to detonate rockets
entity missile, targetlist, targ;
- float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
- float selfdamage, teamdamage, enemydamage;
- edgedamage = WEP_CVAR(devastator, edgedamage);
- coredamage = WEP_CVAR(devastator, damage);
- edgeradius = WEP_CVAR(devastator, radius);
- recipricoledgeradius = 1 / edgeradius;
- selfdamage = 0;
- teamdamage = 0;
- enemydamage = 0;
targetlist = findchainfloat(bot_attack, TRUE);
- missile = find(world, classname, "rocket");
- while (missile)
+ for(missile = world; (missile = find(missile, classname, "rocket")); ) if(missile.realowner == self)
{
- if (missile.realowner != self)
- {
- missile = find(missile, classname, "rocket");
- continue;
- }
targ = targetlist;
- while (targ)
+ while(targ)
{
- d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - missile.origin);
- d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
- // count potential damage according to type of target
- if (targ == self)
- selfdamage = selfdamage + d;
- else if (targ.team == self.team && teamplay)
- teamdamage = teamdamage + d;
- else if (bot_shouldattack(targ))
- enemydamage = enemydamage + d;
- targ = targ.chain;
- }
- missile = find(missile, classname, "rocket");
- }
- float desirabledamage;
- desirabledamage = enemydamage;
- if (time > self.invincible_finished && time > self.spawnshieldtime)
- desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent;
- if (teamplay && self.team)
- desirabledamage = desirabledamage - teamdamage;
-
- missile = find(world, classname, "rocket");
- while (missile)
- {
- if (missile.realowner != self)
- {
- missile = find(missile, classname, "rocket");
- continue;
- }
- makevectors(missile.v_angle);
- targ = targetlist;
- if (skill > 9) // normal players only do this for the target they are tracking
- {
- targ = targetlist;
- while (targ)
+ if(targ != missile.realowner && vlen(targ.origin - missile.origin) < WEP_CVAR(devastator, radius))
{
- if (
- (v_forward * normalize(missile.origin - targ.origin)< 0.1)
- && desirabledamage > 0.1*coredamage
- )self.BUTTON_ATCK2 = TRUE;
- targ = targ.chain;
+ self.BUTTON_ATCK2 = TRUE;
+ break;
}
- }else{
- float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
- //As the distance gets larger, a correct detonation gets near imposible
- //Bots are assumed to use the rocket spawnfunc_light to see if the rocket gets near a player
- if(v_forward * normalize(missile.origin - self.enemy.origin)< 0.1)
- if(IS_PLAYER(self.enemy))
- if(desirabledamage >= 0.1*coredamage)
- if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1))
- self.BUTTON_ATCK2 = TRUE;
- // dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n");
+ targ = targ.chain;
}
-
- missile = find(missile, classname, "rocket");
}
- // if we would be doing at X percent of the core damage, detonate it
- // but don't fire a new shot at the same time!
- if (desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events
- self.BUTTON_ATCK2 = TRUE;
- if ((skill > 6.5) && (selfdamage > self.health))
- self.BUTTON_ATCK2 = FALSE;
- //if(self.BUTTON_ATCK2 == TRUE)
- // dprint(ftos(desirabledamage),"\n");
- if (self.BUTTON_ATCK2 == TRUE) self.BUTTON_ATCK = FALSE;
+
+ if(self.BUTTON_ATCK2) self.BUTTON_ATCK = FALSE;
}
return TRUE;
case WR_THINK:
{
if(WEP_CVAR(devastator, reload_ammo) && self.clip_load < WEP_CVAR(devastator, ammo)) // forced reload
- weapon_action(self.weapon, WR_RELOAD);
+ WEP_ACTION(self.weapon, WR_RELOAD);
else
{
- if (self.BUTTON_ATCK)
+ if(self.BUTTON_ATCK)
{
if(self.rl_release || WEP_CVAR(devastator, guidestop))
if(weapon_prepareattack(0, WEP_CVAR(devastator, refire)))
else
self.rl_release = 1;
- if (self.BUTTON_ATCK2)
+ if(self.BUTTON_ATCK2)
{
rockfound = 0;
for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self)
return TRUE;
}
- case WR_PRECACHE:
+ case WR_INIT:
{
if(autocvar_sv_precacheweapons)
{
- precache_model ("models/flash.md3");
- precache_model ("models/weapons/g_rl.md3");
- precache_model ("models/weapons/v_rl.md3");
- precache_model ("models/weapons/h_rl.iqm");
- precache_sound ("weapons/rocket_det.wav");
- precache_sound ("weapons/rocket_fire.wav");
- precache_sound ("weapons/rocket_mode.wav");
+ precache_model("models/flash.md3");
+ precache_model("models/weapons/g_rl.md3");
+ precache_model("models/weapons/v_rl.md3");
+ precache_model("models/weapons/h_rl.iqm");
+ precache_sound("weapons/rocket_det.wav");
+ precache_sound("weapons/rocket_fire.wav");
+ precache_sound("weapons/rocket_mode.wav");
}
-
- #define WEP_ADD_CVAR(weapon,mode,name) /*nothing*/
- #define WEP_ADD_PROP(weapon,prop,name) get_weaponinfo(WEP_DEVASTATOR).##prop = autocvar_g_balance_##weapon##_##name;
- ARC_SETTINGS(devastator)
- #undef WEP_ADD_CVAR
- #undef WEP_ADD_PROP
-
+ DEVASTATOR_SETTINGS(WEP_SKIPCVAR, WEP_SET_PROP)
return TRUE;
}
case WR_SETUP:
{
- weapon_setup(WEP_DEVASTATOR);
- self.current_ammo = ammo_rockets;
self.rl_release = 1;
return TRUE;
}
ammo_amount = FALSE;
if(WEP_CVAR(devastator, reload_ammo))
{
- if(self.ammo_rockets < WEP_CVAR(devastator, ammo) && self.(weapon_load[WEP_DEVASTATOR]) < WEP_CVAR(devastator, ammo))
+ if(self.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo) && self.(weapon_load[WEP_DEVASTATOR]) < WEP_CVAR(devastator, ammo))
ammo_amount = TRUE;
}
- else if(self.ammo_rockets < WEP_CVAR(devastator, ammo))
+ else if(self.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
ammo_amount = TRUE;
return !ammo_amount;
}
{
return FALSE;
}
+ case WR_CONFIG:
+ {
+ DEVASTATOR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
+ return TRUE;
+ }
case WR_RESETPLAYER:
{
self.rl_release = 0;
}
case WR_RELOAD:
{
- W_Reload(WEP_CVAR(devastator, ammo), WEP_CVAR(devastator, reload_ammo), WEP_CVAR(devastator, reload_time), "weapons/reload.wav");
+ W_Reload(WEP_CVAR(devastator, ammo), "weapons/reload.wav");
return TRUE;
}
case WR_SUICIDEMESSAGE:
return TRUE;
}
- case WR_PRECACHE:
+ case WR_INIT:
{
precache_sound("weapons/rocket_impact.wav");
return TRUE;
}
+ case WR_ZOOMRETICLE:
+ {
+ // no weapon specific image for this weapon
+ return FALSE;
+ }
}
return TRUE;
}