weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(hmg, refire), W_HeavyMachineGun_Attack_Auto);
}
-METHOD(HeavyMachineGun, wr_aim, void(entity thiswep, entity actor))
+METHOD(HeavyMachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, 1000000, 0, 0.001, false);
MUTATOR_CALLHOOK(EditProjectile, actor, missile);
}
-METHOD(RocketPropelledChainsaw, wr_aim, void(entity thiswep, entity actor))
+METHOD(RocketPropelledChainsaw, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR(rpc, speed), 0, WEP_CVAR(rpc, lifetime), false);
}
/** (SERVER) checks ammo for weapon second */
METHOD(Weapon, wr_checkammo2, bool(Weapon this, entity actor, .entity weaponentity)) {return false;}
/** (SERVER) runs bot aiming code for this weapon */
- METHOD(Weapon, wr_aim, void(Weapon this, entity actor)) {}
+ METHOD(Weapon, wr_aim, void(Weapon this, entity actor, .entity weaponentity)) {}
/** (BOTH) precaches models/sounds used by this weapon, also sets up weapon properties */
METHOD(Weapon, wr_init, void(Weapon this)) {}
/** (SERVER) notification number for suicide message (may inspect w_deathtype for details) */
}
}
-METHOD(Arc, wr_aim, void(entity thiswep, entity actor))
+METHOD(Arc, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(WEP_CVAR(arc, beam_botaimspeed))
{
}
}
-METHOD(Blaster, wr_aim, void(entity thiswep, entity actor))
+METHOD(Blaster, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(WEP_CVAR(blaster, secondary))
{
}
}
-METHOD(Crylink, wr_aim, void(entity thiswep, entity actor))
+METHOD(Crylink, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(random() < 0.10)
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(crylink, speed), 0, WEP_CVAR_PRI(crylink, middle_lifetime), false);
MUTATOR_CALLHOOK(EditProjectile, actor, missile);
}
-METHOD(Devastator, wr_aim, void(entity thiswep, entity actor))
+METHOD(Devastator, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
// aim and decide to fire if appropriate
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false);
.float bot_secondary_electromooth;
-METHOD(Electro, wr_aim, void(entity thiswep, entity actor))
+METHOD(Electro, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
PHYS_INPUT_BUTTON_ATCK(actor) = PHYS_INPUT_BUTTON_ATCK2(actor) = false;
if(vdist(actor.origin - actor.enemy.origin, >, 1000)) { actor.bot_secondary_electromooth = 0; }
MUTATOR_CALLHOOK(EditProjectile, actor, proj);
}
-METHOD(Fireball, wr_aim, void(entity thiswep, entity actor))
+METHOD(Fireball, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
PHYS_INPUT_BUTTON_ATCK(actor) = false;
PHYS_INPUT_BUTTON_ATCK2(actor) = false;
weapon_thinkf(actor, weaponentity, theframe, WEP_CVAR_PRI(hagar, refire), W_Hagar_Attack_Auto);
}
-METHOD(Hagar, wr_aim, void(entity thiswep, entity actor))
+METHOD(Hagar, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(random()>0.15)
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
}
}
-METHOD(HLAC, wr_aim, void(entity thiswep, entity actor))
+METHOD(HLAC, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(hlac, speed), 0, WEP_CVAR_PRI(hlac, lifetime), false);
}
}
-METHOD(MachineGun, wr_aim, void(entity thiswep, entity actor))
+METHOD(MachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, 1000000, 0, 0.001, false);
return minfound;
}
-METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor))
+METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
// aim and decide to fire if appropriate
- .entity weaponentity = weaponentities[0]; // TODO: unhardcode
if(actor.(weaponentity).minelayer_mines >= WEP_CVAR(minelayer, limit))
PHYS_INPUT_BUTTON_ATCK(actor) = false;
else
.float bot_secondary_grenademooth;
-METHOD(Mortar, wr_aim, void(entity thiswep, entity actor))
+METHOD(Mortar, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
PHYS_INPUT_BUTTON_ATCK(actor) = false;
PHYS_INPUT_BUTTON_ATCK2(actor) = false;
MUTATOR_CALLHOOK(EditProjectile, actor, gren);
}
-METHOD(PortoLaunch, wr_aim, void(entity thiswep, entity actor))
+METHOD(PortoLaunch, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
PHYS_INPUT_BUTTON_ATCK(actor) = false;
PHYS_INPUT_BUTTON_ATCK2(actor) = false;
.float bot_secondary_riflemooth;
-METHOD(Rifle, wr_aim, void(entity thiswep, entity actor))
+METHOD(Rifle, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
PHYS_INPUT_BUTTON_ATCK(actor) = false;
PHYS_INPUT_BUTTON_ATCK2(actor) = false;
// Begin: Genereal weapon functions
// ============================
-METHOD(Seeker, wr_aim, void(entity thiswep, entity actor))
+METHOD(Seeker, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
- .entity weaponentity = weaponentities[0]; // TODO: unhardcode
if(WEP_CVAR(seeker, type) == 1)
if(W_Seeker_Tagged_Info(actor, weaponentity, actor.enemy) != NULL)
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR(seeker, missile_speed_max), 0, WEP_CVAR(seeker, missile_lifetime), false);
}
}
-METHOD(Shockwave, wr_aim, void(entity thiswep, entity actor))
+METHOD(Shockwave, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(vdist(actor.origin - actor.enemy.origin, <=, WEP_CVAR(shockwave, melee_range)))
{ PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, 1000000, 0, 0.001, false); }
.float shotgun_primarytime;
-METHOD(Shotgun, wr_aim, void(entity thiswep, entity actor))
+METHOD(Shotgun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(vdist(actor.origin - actor.enemy.origin, <=, WEP_CVAR_SEC(shotgun, melee_range)))
PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, 1000000, 0, 0.001, false);
#endif
#ifdef SVQC
-METHOD(Tuba, wr_aim, void(Tuba this, entity actor))
+METHOD(Tuba, wr_aim, void(Tuba this, entity actor, .entity weaponentity))
{
// bots cannot play the Tuba well yet
// I think they should start with the recorder first
}
}
-METHOD(Vaporizer, wr_aim, void(entity thiswep, entity actor))
+METHOD(Vaporizer, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(actor.(thiswep.ammo_field) > 0)
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, 1000000, 0, 1, false);
.float vortex_chargepool_pauseregen_finished;
-METHOD(Vortex, wr_aim, void(entity thiswep, entity actor))
+METHOD(Vortex, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(bot_aim(actor, 1000000, 0, 1, false))
PHYS_INPUT_BUTTON_ATCK(actor) = true;
return;
havocbot_chooseenemy(this);
- if (this.bot_chooseweapontime < time )
+
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- this.bot_chooseweapontime = time + autocvar_bot_ai_chooseweaponinterval;
- havocbot_chooseweapon(this);
+ .entity weaponentity = weaponentities[slot];
+ if(this.(weaponentity).m_weapon != WEP_Null || slot == 0)
+ if(this.(weaponentity).bot_chooseweapontime < time)
+ {
+ this.(weaponentity).bot_chooseweapontime = time + autocvar_bot_ai_chooseweaponinterval;
+ havocbot_chooseweapon(this, weaponentity);
+ }
}
havocbot_aim(this);
lag_update(this);
if(this.weapons)
{
- .entity weaponentity = weaponentities[0]; // TODO: unhardcode
- Weapon w = this.(weaponentity).m_weapon;
- w.wr_aim(w, this);
if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(this))
{
PHYS_INPUT_BUTTON_ATCK(this) = false;
}
else
{
- if(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this))
- this.lastfiredweapon = this.(weaponentity).m_weapon.m_id;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ Weapon w = this.(weaponentity).m_weapon;
+ if(w == WEP_Null && slot != 0)
+ continue;
+ w.wr_aim(w, this, weaponentity);
+ if(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this)) // TODO: what if we didn't fire this weapon, but the previous?
+ this.(weaponentity).lastfiredweapon = this.(weaponentity).m_weapon.m_id;
+ }
}
}
else
// if the bot is not attacking, consider reloading weapons
if (!(this.aistatus & AI_STATUS_ATTACKING))
{
- .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
- // we are currently holding a weapon that's not fully loaded, reload it
- if(skill >= 2) // bots can only reload the held weapon on purpose past this skill
- if(this.(weaponentity).clip_load < this.(weaponentity).clip_size)
- this.impulse = 20; // "press" the reload button, not sure if this is done right
+ if(this.(weaponentity).m_weapon == WEP_Null && slot != 0)
+ continue;
- // if we're not reloading a weapon, switch to any weapon in our invnetory that's not fully loaded to reload it next
- // the code above executes next frame, starting the reloading then
- if(skill >= 5) // bots can only look for unloaded weapons past this skill
- if(this.(weaponentity).clip_load >= 0) // only if we're not reloading a weapon already
- {
- FOREACH(Weapons, it != WEP_Null, LAMBDA(
- if((this.weapons & (it.m_wepset)) && (it.spawnflags & WEP_FLAG_RELOADABLE) && (this.(weaponentity).weapon_load[it.m_id] < it.reloading_ammo))
- this.(weaponentity).m_switchweapon = it;
- ));
+ // we are currently holding a weapon that's not fully loaded, reload it
+ if(skill >= 2) // bots can only reload the held weapon on purpose past this skill
+ if(this.(weaponentity).clip_load < this.(weaponentity).clip_size)
+ this.impulse = 20; // "press" the reload button, not sure if this is done right
+
+ // if we're not reloading a weapon, switch to any weapon in our invnetory that's not fully loaded to reload it next
+ // the code above executes next frame, starting the reloading then
+ if(skill >= 5) // bots can only look for unloaded weapons past this skill
+ if(this.(weaponentity).clip_load >= 0) // only if we're not reloading a weapon already
+ {
+ FOREACH(Weapons, it != WEP_Null, LAMBDA(
+ if((this.weapons & (it.m_wepset)) && (it.spawnflags & WEP_FLAG_RELOADABLE) && (this.(weaponentity).weapon_load[it.m_id] < it.reloading_ammo))
+ this.(weaponentity).m_switchweapon = it;
+ ));
+ }
}
}
}
}
else if(this.health>WEP_CVAR(devastator, damage)*0.5)
{
- .entity weaponentity = weaponentities[0]; // TODO: unhardcode
-
if(this.velocity.z < 0)
- if(client_hasweapon(this, WEP_DEVASTATOR, weaponentity, true, false))
{
- this.movement_x = maxspeed;
-
- if(this.rocketjumptime)
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- if(time > this.rocketjumptime)
+ .entity weaponentity = weaponentities[slot];
+
+ if(this.(weaponentity).m_weapon == WEP_Null && slot != 0)
+ continue;
+
+ if(client_hasweapon(this, WEP_DEVASTATOR, weaponentity, true, false))
{
- PHYS_INPUT_BUTTON_ATCK2(this) = true;
- this.rocketjumptime = 0;
+ this.movement_x = maxspeed;
+
+ if(this.rocketjumptime)
+ {
+ if(time > this.rocketjumptime)
+ {
+ PHYS_INPUT_BUTTON_ATCK2(this) = true;
+ this.rocketjumptime = 0;
+ }
+ return;
+ }
+
+ this.(weaponentity).m_switchweapon = WEP_DEVASTATOR;
+ this.v_angle_x = 90;
+ PHYS_INPUT_BUTTON_ATCK(this) = true;
+ this.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
+ return;
}
- return;
}
-
- this.(weaponentity).m_switchweapon = WEP_DEVASTATOR;
- this.v_angle_x = 90;
- PHYS_INPUT_BUTTON_ATCK(this) = true;
- this.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
- return;
}
}
else
this.havocbot_stickenemy = false;
}
-float havocbot_chooseweapon_checkreload(entity this, int new_weapon)
+float havocbot_chooseweapon_checkreload(entity this, .entity weaponentity, int new_weapon)
{
// bots under this skill cannot find unloaded weapons to reload idly when not in combat,
// so skip this for them, or they'll never get to reload their weapons at all.
return false;
// if this weapon is scheduled for reloading, don't switch to it during combat
- .entity weaponentity = weaponentities[0]; // TODO: unhardcode
if (this.(weaponentity).weapon_load[new_weapon] < 0)
{
bool other_weapon_available = false;
return false;
}
-void havocbot_chooseweapon(entity this)
+void havocbot_chooseweapon(entity this, .entity weaponentity)
{
int i;
- .entity weaponentity = weaponentities[0]; // TODO: unhardcode
-
// ;)
if(g_weaponarena_weapons == WEPSET(TUBA))
{
combo = false;
if(autocvar_bot_ai_weapon_combo)
- if(this.(weaponentity).m_weapon.m_id == this.lastfiredweapon)
+ if(this.(weaponentity).m_weapon.m_id == this.(weaponentity).lastfiredweapon)
if(af > combo_time)
{
combo = true;
w = bot_weapons_far[i];
if ( client_hasweapon(this, Weapons_from(w), weaponentity, true, false) )
{
- if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+ if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, weaponentity, w))
continue;
this.(weaponentity).m_switchweapon = Weapons_from(w);
return;
w = bot_weapons_mid[i];
if ( client_hasweapon(this, Weapons_from(w), weaponentity, true, false) )
{
- if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+ if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, weaponentity, w))
continue;
this.(weaponentity).m_switchweapon = Weapons_from(w);
return;
w = bot_weapons_close[i];
if ( client_hasweapon(this, Weapons_from(w), weaponentity, true, false) )
{
- if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+ if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, weaponentity, w))
continue;
this.(weaponentity).m_switchweapon = Weapons_from(w);
return;
void havocbot_movetogoal(entity this);
void havocbot_chooserole(entity this);
void havocbot_chooseenemy(entity this);
-void havocbot_chooseweapon(entity this);
+void havocbot_chooseweapon(entity this, .entity weaponentity);
void havocbot_bunnyhop(entity this, vector dir);
void havocbot_keyboard_movement(entity this, vector destorg);