/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/* Modifications
Copyright 2003-2004 Bytonic Software
Copyright 2010 Google Inc.
*/
package com.googlecode.gwtquake.shared.game;
import com.googlecode.gwtquake.shared.common.Com;
import com.googlecode.gwtquake.shared.common.Constants;
import com.googlecode.gwtquake.shared.common.Globals;
import com.googlecode.gwtquake.shared.game.adapters.EntInteractAdapter;
import com.googlecode.gwtquake.shared.game.adapters.EntityThinkAdapter;
import com.googlecode.gwtquake.shared.game.adapters.ItemDropAdapter;
import com.googlecode.gwtquake.shared.game.adapters.ItemUseAdapter;
import com.googlecode.gwtquake.shared.game.monsters.MonsterPlayer;
import com.googlecode.gwtquake.shared.server.ServerGame;
import com.googlecode.gwtquake.shared.server.ServerInit;
import com.googlecode.gwtquake.shared.server.ServerSend;
import com.googlecode.gwtquake.shared.server.World;
import com.googlecode.gwtquake.shared.util.Lib;
import com.googlecode.gwtquake.shared.util.Math3D;
public class PlayerWeapon {
public static EntityThinkAdapter Weapon_Grenade = new EntityThinkAdapter() {
public String getID() { return "Weapon_Grenade"; }
public boolean think(Entity ent) {
if ((ent.client.newweapon != null)
&& (ent.client.weaponstate == Constants.WEAPON_READY)) {
ChangeWeapon(ent);
return true;
}
if (ent.client.weaponstate == Constants.WEAPON_ACTIVATING) {
ent.client.weaponstate = Constants.WEAPON_READY;
ent.client.ps.gunframe = 16;
return true;
}
if (ent.client.weaponstate == Constants.WEAPON_READY) {
if (((ent.client.latched_buttons | ent.client.buttons) & Constants.BUTTON_ATTACK) != 0) {
ent.client.latched_buttons &= ~Constants.BUTTON_ATTACK;
if (0 != ent.client.pers.inventory[ent.client.ammo_index]) {
ent.client.ps.gunframe = 1;
ent.client.weaponstate = Constants.WEAPON_FIRING;
ent.client.grenade_time = 0;
} else {
if (GameBase.level.time >= ent.pain_debounce_time) {
ServerGame.PF_StartSound(ent, Constants.CHAN_VOICE, ServerInit.SV_SoundIndex("weapons/noammo.wav"), (float) 1, (float) Constants.ATTN_NORM,
(float) 0);
ent.pain_debounce_time = GameBase.level.time + 1;
}
NoAmmoWeaponChange(ent);
}
return true;
}
if ((ent.client.ps.gunframe == 29)
|| (ent.client.ps.gunframe == 34)
|| (ent.client.ps.gunframe == 39)
|| (ent.client.ps.gunframe == 48)) {
if ((Lib.rand() & 15) != 0)
return true;
}
if (++ent.client.ps.gunframe > 48)
ent.client.ps.gunframe = 16;
return true;
}
if (ent.client.weaponstate == Constants.WEAPON_FIRING) {
if (ent.client.ps.gunframe == 5)
ServerGame.PF_StartSound(ent, Constants.CHAN_WEAPON, ServerInit.SV_SoundIndex("weapons/hgrena1b.wav"), (float) 1, (float) Constants.ATTN_NORM,
(float) 0);
if (ent.client.ps.gunframe == 11) {
if (0 == ent.client.grenade_time) {
ent.client.grenade_time = GameBase.level.time
+ Constants.GRENADE_TIMER + 0.2f;
ent.client.weapon_sound = ServerInit.SV_SoundIndex("weapons/hgrenc1b.wav");
}
// they waited too long, detonate it in their hand
if (!ent.client.grenade_blew_up
&& GameBase.level.time >= ent.client.grenade_time) {
ent.client.weapon_sound = 0;
weapon_grenade_fire(ent, true);
ent.client.grenade_blew_up = true;
}
if ((ent.client.buttons & Constants.BUTTON_ATTACK) != 0)
return true;
if (ent.client.grenade_blew_up) {
if (GameBase.level.time >= ent.client.grenade_time) {
ent.client.ps.gunframe = 15;
ent.client.grenade_blew_up = false;
} else {
return true;
}
}
}
if (ent.client.ps.gunframe == 12) {
ent.client.weapon_sound = 0;
weapon_grenade_fire(ent, false);
}
if ((ent.client.ps.gunframe == 15)
&& (GameBase.level.time < ent.client.grenade_time))
return true;
ent.client.ps.gunframe++;
if (ent.client.ps.gunframe == 16) {
ent.client.grenade_time = 0;
ent.client.weaponstate = Constants.WEAPON_READY;
}
}
return true;
}
};
/*
* ======================================================================
*
* GRENADE LAUNCHER
*
* ======================================================================
*/
public static EntityThinkAdapter weapon_grenadelauncher_fire = new EntityThinkAdapter() {
public String getID() { return "weapon_grenadelauncher_fire"; }
public boolean think(Entity ent) {
float[] offset = { 0, 0, 0 };
float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 };
float[] start = { 0, 0, 0 };
int damage = 120;
float radius;
radius = damage + 40;
if (is_quad)
damage *= 4;
Math3D.VectorSet(offset, 8, 8, ent.viewheight - 8);
Math3D.AngleVectors(ent.client.v_angle, forward, right, null);
P_ProjectSource(ent.client, ent.s.origin, offset, forward, right,
start);
Math3D.VectorScale(forward, -2, ent.client.kick_origin);
ent.client.kick_angles[0] = -1;
GameWeapon.fire_grenade(ent, start, forward, damage, 600, 2.5f, radius);
ServerGame.PF_WriteByte(Constants.svc_muzzleflash);
ServerGame.PF_WriteShort(ent.index);
ServerGame.PF_WriteByte(Constants.MZ_GRENADE | is_silenced);
ServerSend.SV_Multicast(ent.s.origin, Constants.MULTICAST_PVS);
ent.client.ps.gunframe++;
PlayerWeapon.PlayerNoise(ent, start, Constants.PNOISE_WEAPON);
if (0 == ((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO))
ent.client.pers.inventory[ent.client.ammo_index]--;
return true;
}
};
public static EntityThinkAdapter Weapon_GrenadeLauncher = new EntityThinkAdapter() {
public String getID() { return "Weapon_GrenadeLauncher"; }
public boolean think(Entity ent) {
int pause_frames[] = { 34, 51, 59, 0 };
int fire_frames[] = { 6, 0 };
Weapon_Generic(ent, 5, 16, 59, 64, pause_frames, fire_frames,
weapon_grenadelauncher_fire);
return true;
}
};
/*
* ======================================================================
*
* ROCKET
*
* ======================================================================
*/
public static EntityThinkAdapter Weapon_RocketLauncher_Fire = new EntityThinkAdapter() {
public String getID() { return "Weapon_RocketLauncher_Fire"; }
public boolean think(Entity ent) {
float[] offset = { 0, 0, 0 }, start = { 0, 0, 0 };
float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 };
int damage;
float damage_radius;
int radius_damage;
damage = 100 + (int) (Lib.random() * 20.0);
radius_damage = 120;
damage_radius = 120;
if (is_quad) {
damage *= 4;
radius_damage *= 4;
}
Math3D.AngleVectors(ent.client.v_angle, forward, right, null);
Math3D.VectorScale(forward, -2, ent.client.kick_origin);
ent.client.kick_angles[0] = -1;
Math3D.VectorSet(offset, 8, 8, ent.viewheight - 8);
P_ProjectSource(ent.client, ent.s.origin, offset, forward, right,
start);
GameWeapon.fire_rocket(ent, start, forward, damage, 650, damage_radius,
radius_damage);
// send muzzle flash
ServerGame.PF_WriteByte(Constants.svc_muzzleflash);
ServerGame.PF_WriteShort(ent.index);
ServerGame.PF_WriteByte(Constants.MZ_ROCKET | is_silenced);
ServerSend.SV_Multicast(ent.s.origin, Constants.MULTICAST_PVS);
ent.client.ps.gunframe++;
PlayerWeapon.PlayerNoise(ent, start, Constants.PNOISE_WEAPON);
if (0 == ((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO))
ent.client.pers.inventory[ent.client.ammo_index]--;
return true;
}
};
public static EntityThinkAdapter Weapon_RocketLauncher = new EntityThinkAdapter() {
public String getID() { return "Weapon_RocketLauncher"; }
public boolean think(Entity ent) {
int pause_frames[] = { 25, 33, 42, 50, 0 };
int fire_frames[] = { 5, 0 };
Weapon_Generic(ent, 4, 12, 50, 54, pause_frames, fire_frames,
Weapon_RocketLauncher_Fire);
return true;
}
};
public static EntityThinkAdapter Weapon_Blaster_Fire = new EntityThinkAdapter() {
public String getID() { return "Weapon_Blaster_Fire"; }
public boolean think(Entity ent) {
int damage;
if (GameBase.deathmatch.value != 0)
damage = 15;
else
damage = 10;
Blaster_Fire(ent, Globals.vec3_origin, damage, false,
Constants.EF_BLASTER);
ent.client.ps.gunframe++;
return true;
}
};
public static EntityThinkAdapter Weapon_Blaster = new EntityThinkAdapter() {
public String getID() { return "Weapon_Blaster"; }
public boolean think(Entity ent) {
int pause_frames[] = { 19, 32, 0 };
int fire_frames[] = { 5, 0 };
Weapon_Generic(ent, 4, 8, 52, 55, pause_frames, fire_frames,
Weapon_Blaster_Fire);
return true;
}
};
public static EntityThinkAdapter Weapon_HyperBlaster_Fire = new EntityThinkAdapter() {
public String getID() { return "Weapon_HyperBlaster_Fire"; }
public boolean think(Entity ent) {
float rotation;
float[] offset = { 0, 0, 0 };
int effect;
int damage;
ent.client.weapon_sound = ServerInit.SV_SoundIndex("weapons/hyprbl1a.wav");
if (0 == (ent.client.buttons & Constants.BUTTON_ATTACK)) {
ent.client.ps.gunframe++;
} else {
if (0 == ent.client.pers.inventory[ent.client.ammo_index]) {
if (GameBase.level.time >= ent.pain_debounce_time) {
ServerGame.PF_StartSound(ent, Constants.CHAN_VOICE, ServerInit.SV_SoundIndex("weapons/noammo.wav"), (float) 1, (float) Constants.ATTN_NORM,
(float) 0);
ent.pain_debounce_time = GameBase.level.time + 1;
}
NoAmmoWeaponChange(ent);
} else {
rotation = (float) ((ent.client.ps.gunframe - 5) * 2
* Math.PI / 6);
offset[0] = (float) (-4 * Math.sin(rotation));
offset[1] = 0f;
offset[2] = (float) (4 * Math.cos(rotation));
if ((ent.client.ps.gunframe == 6)
|| (ent.client.ps.gunframe == 9))
effect = Constants.EF_HYPERBLASTER;
else
effect = 0;
if (GameBase.deathmatch.value != 0)
damage = 15;
else
damage = 20;
Blaster_Fire(ent, offset, damage, true, effect);
if (0 == ((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO))
ent.client.pers.inventory[ent.client.ammo_index]--;
ent.client.anim_priority = Constants.ANIM_ATTACK;
if ((ent.client.ps.pmove.pm_flags & PlayerMove.PMF_DUCKED) != 0) {
ent.s.frame = MonsterPlayer.FRAME_crattak1 - 1;
ent.client.anim_end = MonsterPlayer.FRAME_crattak9;
} else {
ent.s.frame = MonsterPlayer.FRAME_attack1 - 1;
ent.client.anim_end = MonsterPlayer.FRAME_attack8;
}
}
ent.client.ps.gunframe++;
if (ent.client.ps.gunframe == 12
&& 0 != ent.client.pers.inventory[ent.client.ammo_index])
ent.client.ps.gunframe = 6;
}
if (ent.client.ps.gunframe == 12) {
ServerGame.PF_StartSound(ent, Constants.CHAN_AUTO, ServerInit.SV_SoundIndex("weapons/hyprbd1a.wav"), (float) 1, (float) Constants.ATTN_NORM,
(float) 0);
ent.client.weapon_sound = 0;
}
return true;
}
};
public static EntityThinkAdapter Weapon_HyperBlaster = new EntityThinkAdapter() {
public String getID() { return "Weapon_HyperBlaster"; }
public boolean think(Entity ent) {
int pause_frames[] = { 0 };
int fire_frames[] = { 6, 7, 8, 9, 10, 11, 0 };
Weapon_Generic(ent, 5, 20, 49, 53, pause_frames, fire_frames,
Weapon_HyperBlaster_Fire);
return true;
}
};
public static EntityThinkAdapter Weapon_Machinegun = new EntityThinkAdapter() {
public String getID() { return "Weapon_Machinegun"; }
public boolean think(Entity ent) {
int pause_frames[] = { 23, 45, 0 };
int fire_frames[] = { 4, 5, 0 };
Weapon_Generic(ent, 3, 5, 45, 49, pause_frames, fire_frames,
Machinegun_Fire);
return true;
}
};
public static EntityThinkAdapter Weapon_Chaingun = new EntityThinkAdapter() {
public String getID() { return "Weapon_Chaingun"; }
public boolean think(Entity ent) {
int pause_frames[] = { 38, 43, 51, 61, 0 };
int fire_frames[] = { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 0 };
Weapon_Generic(ent, 4, 31, 61, 64, pause_frames, fire_frames,
Chaingun_Fire);
return true;
}
};
/*
* ======================================================================
*
* SHOTGUN / SUPERSHOTGUN
*
* ======================================================================
*/
public static EntityThinkAdapter weapon_shotgun_fire = new EntityThinkAdapter() {
public String getID() { return "weapon_shotgun_fire"; }
public boolean think(Entity ent) {
float[] start = { 0, 0, 0 };
float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 };
float[] offset = { 0, 0, 0 };
int damage = 4;
int kick = 8;
if (ent.client.ps.gunframe == 9) {
ent.client.ps.gunframe++;
return true;
}
Math3D.AngleVectors(ent.client.v_angle, forward, right, null);
Math3D.VectorScale(forward, -2, ent.client.kick_origin);
ent.client.kick_angles[0] = -2;
Math3D.VectorSet(offset, 0, 8, ent.viewheight - 8);
P_ProjectSource(ent.client, ent.s.origin, offset, forward, right,
start);
if (is_quad) {
damage *= 4;
kick *= 4;
}
if (GameBase.deathmatch.value != 0)
GameWeapon.fire_shotgun(ent, start, forward, damage, kick, 500, 500,
Constants.DEFAULT_DEATHMATCH_SHOTGUN_COUNT,
Constants.MOD_SHOTGUN);
else
GameWeapon.fire_shotgun(ent, start, forward, damage, kick, 500, 500,
Constants.DEFAULT_SHOTGUN_COUNT, Constants.MOD_SHOTGUN);
// send muzzle flash
ServerGame.PF_WriteByte(Constants.svc_muzzleflash);
ServerGame.PF_WriteShort(ent.index);
ServerGame.PF_WriteByte(Constants.MZ_SHOTGUN | is_silenced);
ServerSend.SV_Multicast(ent.s.origin, Constants.MULTICAST_PVS);
ent.client.ps.gunframe++;
PlayerWeapon.PlayerNoise(ent, start, Constants.PNOISE_WEAPON);
if (0 == ((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO))
ent.client.pers.inventory[ent.client.ammo_index]--;
return true;
}
};
public static EntityThinkAdapter Weapon_Shotgun = new EntityThinkAdapter() {
public String getID() { return "Weapon_Shotgun"; }
public boolean think(Entity ent) {
int pause_frames[] = { 22, 28, 34, 0 };
int fire_frames[] = { 8, 9, 0 };
Weapon_Generic(ent, 7, 18, 36, 39, pause_frames, fire_frames,
weapon_shotgun_fire);
return true;
}
};
public static EntityThinkAdapter weapon_supershotgun_fire = new EntityThinkAdapter() {
public String getID() { return "weapon_supershotgun_fire"; }
public boolean think(Entity ent) {
float[] start = { 0, 0, 0 };
float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 };
float[] offset = { 0, 0, 0 };
float[] v = { 0, 0, 0 };
int damage = 6;
int kick = 12;
Math3D.AngleVectors(ent.client.v_angle, forward, right, null);
Math3D.VectorScale(forward, -2, ent.client.kick_origin);
ent.client.kick_angles[0] = -2;
Math3D.VectorSet(offset, 0, 8, ent.viewheight - 8);
P_ProjectSource(ent.client, ent.s.origin, offset, forward, right,
start);
if (is_quad) {
damage *= 4;
kick *= 4;
}
v[Constants.PITCH] = ent.client.v_angle[Constants.PITCH];
v[Constants.YAW] = ent.client.v_angle[Constants.YAW] - 5;
v[Constants.ROLL] = ent.client.v_angle[Constants.ROLL];
Math3D.AngleVectors(v, forward, null, null);
GameWeapon.fire_shotgun(ent, start, forward, damage, kick,
Constants.DEFAULT_SHOTGUN_HSPREAD,
Constants.DEFAULT_SHOTGUN_VSPREAD,
Constants.DEFAULT_SSHOTGUN_COUNT / 2, Constants.MOD_SSHOTGUN);
v[Constants.YAW] = ent.client.v_angle[Constants.YAW] + 5;
Math3D.AngleVectors(v, forward, null, null);
GameWeapon.fire_shotgun(ent, start, forward, damage, kick,
Constants.DEFAULT_SHOTGUN_HSPREAD,
Constants.DEFAULT_SHOTGUN_VSPREAD,
Constants.DEFAULT_SSHOTGUN_COUNT / 2, Constants.MOD_SSHOTGUN);
// send muzzle flash
ServerGame.PF_WriteByte(Constants.svc_muzzleflash);
ServerGame.PF_WriteShort(ent.index);
ServerGame.PF_WriteByte(Constants.MZ_SSHOTGUN | is_silenced);
ServerSend.SV_Multicast(ent.s.origin, Constants.MULTICAST_PVS);
ent.client.ps.gunframe++;
PlayerWeapon.PlayerNoise(ent, start, Constants.PNOISE_WEAPON);
if (0 == ((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO))
ent.client.pers.inventory[ent.client.ammo_index] -= 2;
return true;
}
};
public static EntityThinkAdapter Weapon_SuperShotgun = new EntityThinkAdapter() {
public String getID() { return "Weapon_SuperShotgun"; }
public boolean think(Entity ent) {
int pause_frames[] = { 29, 42, 57, 0 };
int fire_frames[] = { 7, 0 };
Weapon_Generic(ent, 6, 17, 57, 61, pause_frames, fire_frames,
weapon_supershotgun_fire);
return true;
}
};
/*
* ======================================================================
*
* RAILGUN
*
* ======================================================================
*/
public static EntityThinkAdapter weapon_railgun_fire = new EntityThinkAdapter() {
public String getID() { return "weapon_railgun_fire"; }
public boolean think(Entity ent) {
float[] start = { 0, 0, 0 };
float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 };
float[] offset = { 0, 0, 0 };
int damage;
int kick;
if (GameBase.deathmatch.value != 0) { // normal damage is too
// extreme in dm
damage = 100;
kick = 200;
} else {
damage = 150;
kick = 250;
}
if (is_quad) {
damage *= 4;
kick *= 4;
}
Math3D.AngleVectors(ent.client.v_angle, forward, right, null);
Math3D.VectorScale(forward, -3, ent.client.kick_origin);
ent.client.kick_angles[0] = -3;
Math3D.VectorSet(offset, 0, 7, ent.viewheight - 8);
P_ProjectSource(ent.client, ent.s.origin, offset, forward, right,
start);
GameWeapon.fire_rail(ent, start, forward, damage, kick);
// send muzzle flash
ServerGame.PF_WriteByte(Constants.svc_muzzleflash);
ServerGame.PF_WriteShort(ent.index);
ServerGame.PF_WriteByte(Constants.MZ_RAILGUN | is_silenced);
ServerSend.SV_Multicast(ent.s.origin, Constants.MULTICAST_PVS);
ent.client.ps.gunframe++;
PlayerWeapon.PlayerNoise(ent, start, Constants.PNOISE_WEAPON);
if (0 == ((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO))
ent.client.pers.inventory[ent.client.ammo_index]--;
return true;
}
};
public static EntityThinkAdapter Weapon_Railgun = new EntityThinkAdapter() {
public String getID() { return "Weapon_Railgun"; }
public boolean think(Entity ent) {
int pause_frames[] = { 56, 0 };
int fire_frames[] = { 4, 0 };
Weapon_Generic(ent, 3, 18, 56, 61, pause_frames, fire_frames,
weapon_railgun_fire);
return true;
}
};
/*
* ======================================================================
*
* BFG10K
*
* ======================================================================
*/
public static EntityThinkAdapter weapon_bfg_fire = new EntityThinkAdapter() {
public String getID() { return "weapon_bfg_fire"; }
public boolean think(Entity ent) {
float[] offset = { 0, 0, 0 }, start = { 0, 0, 0 };
float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 };
int damage;
float damage_radius = 1000;
if (GameBase.deathmatch.value != 0)
damage = 200;
else
damage = 500;
if (ent.client.ps.gunframe == 9) {
// send muzzle flash
ServerGame.PF_WriteByte(Constants.svc_muzzleflash);
ServerGame.PF_WriteShort(ent.index);
ServerGame.PF_WriteByte(Constants.MZ_BFG | is_silenced);
ServerSend.SV_Multicast(ent.s.origin, Constants.MULTICAST_PVS);
ent.client.ps.gunframe++;
PlayerWeapon.PlayerNoise(ent, start, Constants.PNOISE_WEAPON);
return true;
}
// cells can go down during windup (from power armor hits), so
// check again and abort firing if we don't have enough now
if (ent.client.pers.inventory[ent.client.ammo_index] < 50) {
ent.client.ps.gunframe++;
return true;
}
if (is_quad)
damage *= 4;
Math3D.AngleVectors(ent.client.v_angle, forward, right, null);
Math3D.VectorScale(forward, -2, ent.client.kick_origin);
// make a big pitch kick with an inverse fall
ent.client.v_dmg_pitch = -40;
ent.client.v_dmg_roll = Lib.crandom() * 8;
ent.client.v_dmg_time = GameBase.level.time + Constants.DAMAGE_TIME;
Math3D.VectorSet(offset, 8, 8, ent.viewheight - 8);
P_ProjectSource(ent.client, ent.s.origin, offset, forward, right,
start);
GameWeapon.fire_bfg(ent, start, forward, damage, 400, damage_radius);
ent.client.ps.gunframe++;
PlayerWeapon.PlayerNoise(ent, start, Constants.PNOISE_WEAPON);
if (0 == ((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO))
ent.client.pers.inventory[ent.client.ammo_index] -= 50;
return true;
}
};
public static EntityThinkAdapter Weapon_BFG = new EntityThinkAdapter() {
public String getID() { return "Weapon_BFG"; }
public boolean think(Entity ent) {
Weapon_Generic(ent, 8, 32, 55, 58, pause_frames, fire_frames,
weapon_bfg_fire);
return true;
}
};
public static boolean is_quad;
public static byte is_silenced;
/*
* ================
* Use_Weapon
*
* Make the weapon ready if there is ammo
* ================
*/
public static ItemUseAdapter Use_Weapon = new ItemUseAdapter() {
public String getID() { return "Use_Weapon"; }
public void use(Entity ent, GameItem item) {
int ammo_index;
GameItem ammo_item;
// see if we're already using it
if (item == ent.client.pers.weapon)
return;
if (item.ammo != null && 0 == GameBase.g_select_empty.value
&& 0 == (item.flags & Constants.IT_AMMO)) {
ammo_item = GameItems.FindItem(item.ammo);
ammo_index = GameItems.ITEM_INDEX(ammo_item);
if (0 == ent.client.pers.inventory[ammo_index]) {
ServerGame.PF_cprintf(ent, Constants.PRINT_HIGH, "No "
+ ammo_item.pickup_name + " for "
+ item.pickup_name + ".\n");
return;
}
if (ent.client.pers.inventory[ammo_index] < item.quantity) {
ServerGame.PF_cprintf(ent, Constants.PRINT_HIGH, "Not enough "
+ ammo_item.pickup_name + " for "
+ item.pickup_name + ".\n");
return;
}
}
// change to this weapon when down
ent.client.newweapon = item;
}
};
/*
* ================
* Drop_Weapon
* ================
*/
public static ItemDropAdapter Drop_Weapon = new ItemDropAdapter() {
public String getID() { return "Drop_Weapon"; }
public void drop(Entity ent, GameItem item) {
int index;
if (0 != ((int) (GameBase.dmflags.value) & Constants.DF_WEAPONS_STAY))
return;
index = GameItems.ITEM_INDEX(item);
// see if we're already using it
if (((item == ent.client.pers.weapon) || (item == ent.client.newweapon))
&& (ent.client.pers.inventory[index] == 1)) {
ServerGame.PF_cprintf(ent, Constants.PRINT_HIGH, "Can't drop current weapon\n");
return;
}
GameItems.Drop_Item(ent, item);
ent.client.pers.inventory[index]--;
}
};
/*
* ======================================================================
*
* MACHINEGUN / CHAINGUN
*
* ======================================================================
*/
public static EntityThinkAdapter Machinegun_Fire = new EntityThinkAdapter() {
public String getID() { return "Machinegun_Fire"; }
public boolean think(Entity ent) {
int i;
float[] start = { 0, 0, 0 };
float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 };
float[] angles = { 0, 0, 0 };
int damage = 8;
int kick = 2;
float[] offset = { 0, 0, 0 };
if (0 == (ent.client.buttons & Constants.BUTTON_ATTACK)) {
ent.client.machinegun_shots = 0;
ent.client.ps.gunframe++;
return true;
}
if (ent.client.ps.gunframe == 5)
ent.client.ps.gunframe = 4;
else
ent.client.ps.gunframe = 5;
if (ent.client.pers.inventory[ent.client.ammo_index] < 1) {
ent.client.ps.gunframe = 6;
if (GameBase.level.time >= ent.pain_debounce_time) {
ServerGame.PF_StartSound(ent, Constants.CHAN_VOICE, ServerInit.SV_SoundIndex("weapons/noammo.wav"), (float) 1, (float) Constants.ATTN_NORM,
(float) 0);
ent.pain_debounce_time = GameBase.level.time + 1;
}
NoAmmoWeaponChange(ent);
return true;
}
if (is_quad) {
damage *= 4;
kick *= 4;
}
for (i = 1; i < 3; i++) {
ent.client.kick_origin[i] = Lib.crandom() * 0.35f;
ent.client.kick_angles[i] = Lib.crandom() * 0.7f;
}
ent.client.kick_origin[0] = Lib.crandom() * 0.35f;
ent.client.kick_angles[0] = ent.client.machinegun_shots * -1.5f;
// raise the gun as it is firing
if (0 == GameBase.deathmatch.value) {
ent.client.machinegun_shots++;
if (ent.client.machinegun_shots > 9)
ent.client.machinegun_shots = 9;
}
// get start / end positions
Math3D
.VectorAdd(ent.client.v_angle, ent.client.kick_angles,
angles);
Math3D.AngleVectors(angles, forward, right, null);
Math3D.VectorSet(offset, 0, 8, ent.viewheight - 8);
P_ProjectSource(ent.client, ent.s.origin, offset, forward, right,
start);
GameWeapon.fire_bullet(ent, start, forward, damage, kick,
Constants.DEFAULT_BULLET_HSPREAD,
Constants.DEFAULT_BULLET_VSPREAD, Constants.MOD_MACHINEGUN);
ServerGame.PF_WriteByte(Constants.svc_muzzleflash);
ServerGame.PF_WriteShort(ent.index);
ServerGame.PF_WriteByte(Constants.MZ_MACHINEGUN | is_silenced);
ServerSend.SV_Multicast(ent.s.origin, Constants.MULTICAST_PVS);
PlayerWeapon.PlayerNoise(ent, start, Constants.PNOISE_WEAPON);
if (0 == ((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO))
ent.client.pers.inventory[ent.client.ammo_index]--;
ent.client.anim_priority = Constants.ANIM_ATTACK;
if ((ent.client.ps.pmove.pm_flags & PlayerMove.PMF_DUCKED) != 0) {
ent.s.frame = MonsterPlayer.FRAME_crattak1
- (int) (Lib.random() + 0.25);
ent.client.anim_end = MonsterPlayer.FRAME_crattak9;
} else {
ent.s.frame = MonsterPlayer.FRAME_attack1
- (int) (Lib.random() + 0.25);
ent.client.anim_end = MonsterPlayer.FRAME_attack8;
}
return true;
}
};
public static EntityThinkAdapter Chaingun_Fire = new EntityThinkAdapter() {
public String getID() { return "Chaingun_Fire"; }
public boolean think(Entity ent) {
int i;
int shots;
float[] start = { 0, 0, 0 };
float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 }, up = { 0, 0, 0 };
float r, u;
float[] offset = { 0, 0, 0 };
int damage;
int kick = 2;
if (GameBase.deathmatch.value != 0)
damage = 6;
else
damage = 8;
if (ent.client.ps.gunframe == 5)
ServerGame.PF_StartSound(ent, Constants.CHAN_AUTO, ServerInit.SV_SoundIndex("weapons/chngnu1a.wav"), (float) 1, (float) Constants.ATTN_IDLE,
(float) 0);
if ((ent.client.ps.gunframe == 14)
&& 0 == (ent.client.buttons & Constants.BUTTON_ATTACK)) {
ent.client.ps.gunframe = 32;
ent.client.weapon_sound = 0;
return true;
} else if ((ent.client.ps.gunframe == 21)
&& (ent.client.buttons & Constants.BUTTON_ATTACK) != 0
&& 0 != ent.client.pers.inventory[ent.client.ammo_index]) {
ent.client.ps.gunframe = 15;
} else {
ent.client.ps.gunframe++;
}
if (ent.client.ps.gunframe == 22) {
ent.client.weapon_sound = 0;
ServerGame.PF_StartSound(ent, Constants.CHAN_AUTO, ServerInit.SV_SoundIndex("weapons/chngnd1a.wav"), (float) 1, (float) Constants.ATTN_IDLE,
(float) 0);
} else {
ent.client.weapon_sound = ServerInit.SV_SoundIndex("weapons/chngnl1a.wav");
}
ent.client.anim_priority = Constants.ANIM_ATTACK;
if ((ent.client.ps.pmove.pm_flags & PlayerMove.PMF_DUCKED) != 0) {
ent.s.frame = MonsterPlayer.FRAME_crattak1
- (ent.client.ps.gunframe & 1);
ent.client.anim_end = MonsterPlayer.FRAME_crattak9;
} else {
ent.s.frame = MonsterPlayer.FRAME_attack1
- (ent.client.ps.gunframe & 1);
ent.client.anim_end = MonsterPlayer.FRAME_attack8;
}
if (ent.client.ps.gunframe <= 9)
shots = 1;
else if (ent.client.ps.gunframe <= 14) {
if ((ent.client.buttons & Constants.BUTTON_ATTACK) != 0)
shots = 2;
else
shots = 1;
} else
shots = 3;
if (ent.client.pers.inventory[ent.client.ammo_index] < shots)
shots = ent.client.pers.inventory[ent.client.ammo_index];
if (0 == shots) {
if (GameBase.level.time >= ent.pain_debounce_time) {
ServerGame.PF_StartSound(ent, Constants.CHAN_VOICE, ServerInit.SV_SoundIndex("weapons/noammo.wav"), (float) 1, (float) Constants.ATTN_NORM,
(float) 0);
ent.pain_debounce_time = GameBase.level.time + 1;
}
NoAmmoWeaponChange(ent);
return true;
}
if (is_quad) {
damage *= 4;
kick *= 4;
}
for (i = 0; i < 3; i++) {
ent.client.kick_origin[i] = Lib.crandom() * 0.35f;
ent.client.kick_angles[i] = Lib.crandom() * 0.7f;
}
for (i = 0; i < shots; i++) {
// get start / end positions
Math3D.AngleVectors(ent.client.v_angle, forward, right, up);
r = 7 + Lib.crandom() * 4;
u = Lib.crandom() * 4;
Math3D.VectorSet(offset, 0, r, u + ent.viewheight - 8);
P_ProjectSource(ent.client, ent.s.origin, offset, forward,
right, start);
GameWeapon.fire_bullet(ent, start, forward, damage, kick,
Constants.DEFAULT_BULLET_HSPREAD,
Constants.DEFAULT_BULLET_VSPREAD, Constants.MOD_CHAINGUN);
}
// send muzzle flash
ServerGame.PF_WriteByte(Constants.svc_muzzleflash);
ServerGame.PF_WriteShort(ent.index);
ServerGame.PF_WriteByte((Constants.MZ_CHAINGUN1 + shots - 1)
| is_silenced);
ServerSend.SV_Multicast(ent.s.origin, Constants.MULTICAST_PVS);
PlayerWeapon.PlayerNoise(ent, start, Constants.PNOISE_WEAPON);
if (0 == ((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO))
ent.client.pers.inventory[ent.client.ammo_index] -= shots;
return true;
}
};
public static int pause_frames[] = { 39, 45, 50, 55, 0 };
public static int fire_frames[] = { 9, 17, 0 };
public static EntInteractAdapter Pickup_Weapon = new EntInteractAdapter() {
public String getID() { return "Pickup_Weapon"; }
public boolean interact(Entity ent, Entity other) {
int index;
GameItem ammo;
index = GameItems.ITEM_INDEX(ent.item);
if ((((int) (GameBase.dmflags.value) & Constants.DF_WEAPONS_STAY) != 0 || GameBase.coop.value != 0)
&& 0 != other.client.pers.inventory[index]) {
if (0 == (ent.spawnflags & (Constants.DROPPED_ITEM | Constants.DROPPED_PLAYER_ITEM)))
return false; // leave the weapon for others to pickup
}
other.client.pers.inventory[index]++;
if (0 == (ent.spawnflags & Constants.DROPPED_ITEM)) {
// give them some ammo with it
ammo = GameItems.FindItem(ent.item.ammo);
if (((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO) != 0)
GameItems.Add_Ammo(other, ammo, 1000);
else
GameItems.Add_Ammo(other, ammo, ammo.quantity);
if (0 == (ent.spawnflags & Constants.DROPPED_PLAYER_ITEM)) {
if (GameBase.deathmatch.value != 0) {
if (((int) (GameBase.dmflags.value) & Constants.DF_WEAPONS_STAY) != 0)
ent.flags |= Constants.FL_RESPAWN;
else
GameItems.SetRespawn(ent, 30);
}
if (GameBase.coop.value != 0)
ent.flags |= Constants.FL_RESPAWN;
}
}
if (other.client.pers.weapon != ent.item
&& (other.client.pers.inventory[index] == 1)
&& (0 == GameBase.deathmatch.value || other.client.pers.weapon == GameItems
.FindItem("blaster")))
other.client.newweapon = ent.item;
return true;
}
};
public static void P_ProjectSource(GameClient client, float[] point,
float[] distance, float[] forward, float[] right, float[] result) {
float[] _distance = { 0, 0, 0 };
Math3D.VectorCopy(distance, _distance);
if (client.pers.hand == Constants.LEFT_HANDED)
_distance[1] *= -1;
else if (client.pers.hand == Constants.CENTER_HANDED)
_distance[1] = 0;
Math3D.G_ProjectSource(point, _distance, forward, right, result);
}
/*
* ===============
* ChangeWeapon
*
* The old weapon has been dropped all the way, so make the new one current
* ===============
*/
public static void ChangeWeapon(Entity ent) {
int i;
if (ent.client.grenade_time != 0) {
ent.client.grenade_time = GameBase.level.time;
ent.client.weapon_sound = 0;
weapon_grenade_fire(ent, false);
ent.client.grenade_time = 0;
}
ent.client.pers.lastweapon = ent.client.pers.weapon;
ent.client.pers.weapon = ent.client.newweapon;
ent.client.newweapon = null;
ent.client.machinegun_shots = 0;
// set visible model
if (ent.s.modelindex == 255) {
if (ent.client.pers.weapon != null)
i = ((ent.client.pers.weapon.weapmodel & 0xff) << 8);
else
i = 0;
ent.s.skinnum = (ent.index - 1) | i;
}
if (ent.client.pers.weapon != null
&& ent.client.pers.weapon.ammo != null)
ent.client.ammo_index = GameItems.ITEM_INDEX(GameItems
.FindItem(ent.client.pers.weapon.ammo));
else
ent.client.ammo_index = 0;
if (ent.client.pers.weapon == null) { // dead
ent.client.ps.gunindex = 0;
return;
}
ent.client.weaponstate = Constants.WEAPON_ACTIVATING;
ent.client.ps.gunframe = 0;
ent.client.ps.gunindex = ServerInit.SV_ModelIndex(ent.client.pers.weapon.view_model);
ent.client.anim_priority = Constants.ANIM_PAIN;
if ((ent.client.ps.pmove.pm_flags & PlayerMove.PMF_DUCKED) != 0) {
ent.s.frame = MonsterPlayer.FRAME_crpain1;
ent.client.anim_end = MonsterPlayer.FRAME_crpain4;
} else {
ent.s.frame = MonsterPlayer.FRAME_pain301;
ent.client.anim_end = MonsterPlayer.FRAME_pain304;
}
}
/*
* =================
* NoAmmoWeaponChange
* =================
*/
public static void NoAmmoWeaponChange(Entity ent) {
if (0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("slugs"))]
&& 0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("railgun"))]) {
ent.client.newweapon = GameItems.FindItem("railgun");
return;
}
if (0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("cells"))]
&& 0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("hyperblaster"))]) {
ent.client.newweapon = GameItems.FindItem("hyperblaster");
return;
}
if (0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("bullets"))]
&& 0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("chaingun"))]) {
ent.client.newweapon = GameItems.FindItem("chaingun");
return;
}
if (0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("bullets"))]
&& 0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("machinegun"))]) {
ent.client.newweapon = GameItems.FindItem("machinegun");
return;
}
if (ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("shells"))] > 1
&& 0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("super shotgun"))]) {
ent.client.newweapon = GameItems.FindItem("super shotgun");
return;
}
if (0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("shells"))]
&& 0 != ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems
.FindItem("shotgun"))]) {
ent.client.newweapon = GameItems.FindItem("shotgun");
return;
}
ent.client.newweapon = GameItems.FindItem("blaster");
}
/*
* =================
* Think_Weapon
*
* Called by ClientBeginServerFrame and ClientThink
* =================
*/
public static void Think_Weapon(Entity ent) {
// if just died, put the weapon away
if (ent.health < 1) {
ent.client.newweapon = null;
ChangeWeapon(ent);
}
// call active weapon think routine
if (null != ent.client.pers.weapon
&& null != ent.client.pers.weapon.weaponthink) {
is_quad = (ent.client.quad_framenum > GameBase.level.framenum);
if (ent.client.silencer_shots != 0)
is_silenced = (byte) Constants.MZ_SILENCED;
else
is_silenced = 0;
ent.client.pers.weapon.weaponthink.think(ent);
}
}
/*
* ================
* Weapon_Generic
*
* A generic function to handle the basics of weapon thinking
* ================
*/
public static void Weapon_Generic(Entity ent, int FRAME_ACTIVATE_LAST,
int FRAME_FIRE_LAST, int FRAME_IDLE_LAST,
int FRAME_DEACTIVATE_LAST, int pause_frames[], int fire_frames[],
EntityThinkAdapter fire) {
int FRAME_FIRE_FIRST = (FRAME_ACTIVATE_LAST + 1);
int FRAME_IDLE_FIRST = (FRAME_FIRE_LAST + 1);
int FRAME_DEACTIVATE_FIRST = (FRAME_IDLE_LAST + 1);
int n;
if (ent.deadflag != 0 || ent.s.modelindex != 255) // VWep animations
// screw up corpses
{
return;
}
if (ent.client.weaponstate == Constants.WEAPON_DROPPING) {
if (ent.client.ps.gunframe == FRAME_DEACTIVATE_LAST) {
ChangeWeapon(ent);
return;
} else if ((FRAME_DEACTIVATE_LAST - ent.client.ps.gunframe) == 4) {
ent.client.anim_priority = Constants.ANIM_REVERSE;
if ((ent.client.ps.pmove.pm_flags & PlayerMove.PMF_DUCKED) != 0) {
ent.s.frame = MonsterPlayer.FRAME_crpain4 + 1;
ent.client.anim_end = MonsterPlayer.FRAME_crpain1;
} else {
ent.s.frame = MonsterPlayer.FRAME_pain304 + 1;
ent.client.anim_end = MonsterPlayer.FRAME_pain301;
}
}
ent.client.ps.gunframe++;
return;
}
if (ent.client.weaponstate == Constants.WEAPON_ACTIVATING) {
if (ent.client.ps.gunframe == FRAME_ACTIVATE_LAST) {
ent.client.weaponstate = Constants.WEAPON_READY;
ent.client.ps.gunframe = FRAME_IDLE_FIRST;
return;
}
ent.client.ps.gunframe++;
return;
}
if ((ent.client.newweapon != null)
&& (ent.client.weaponstate != Constants.WEAPON_FIRING)) {
ent.client.weaponstate = Constants.WEAPON_DROPPING;
ent.client.ps.gunframe = FRAME_DEACTIVATE_FIRST;
if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4) {
ent.client.anim_priority = Constants.ANIM_REVERSE;
if ((ent.client.ps.pmove.pm_flags & PlayerMove.PMF_DUCKED) != 0) {
ent.s.frame = MonsterPlayer.FRAME_crpain4 + 1;
ent.client.anim_end = MonsterPlayer.FRAME_crpain1;
} else {
ent.s.frame = MonsterPlayer.FRAME_pain304 + 1;
ent.client.anim_end = MonsterPlayer.FRAME_pain301;
}
}
return;
}
if (ent.client.weaponstate == Constants.WEAPON_READY) {
if (((ent.client.latched_buttons | ent.client.buttons) & Constants.BUTTON_ATTACK) != 0) {
ent.client.latched_buttons &= ~Constants.BUTTON_ATTACK;
if ((0 == ent.client.ammo_index)
|| (ent.client.pers.inventory[ent.client.ammo_index] >= ent.client.pers.weapon.quantity)) {
ent.client.ps.gunframe = FRAME_FIRE_FIRST;
ent.client.weaponstate = Constants.WEAPON_FIRING;
// start the animation
ent.client.anim_priority = Constants.ANIM_ATTACK;
if ((ent.client.ps.pmove.pm_flags & PlayerMove.PMF_DUCKED) != 0) {
ent.s.frame = MonsterPlayer.FRAME_crattak1 - 1;
ent.client.anim_end = MonsterPlayer.FRAME_crattak9;
} else {
ent.s.frame = MonsterPlayer.FRAME_attack1 - 1;
ent.client.anim_end = MonsterPlayer.FRAME_attack8;
}
} else {
if (GameBase.level.time >= ent.pain_debounce_time) {
ServerGame.PF_StartSound(ent, Constants.CHAN_VOICE, ServerInit.SV_SoundIndex("weapons/noammo.wav"), (float) 1, (float) Constants.ATTN_NORM,
(float) 0);
ent.pain_debounce_time = GameBase.level.time + 1;
}
NoAmmoWeaponChange(ent);
}
} else {
if (ent.client.ps.gunframe == FRAME_IDLE_LAST) {
ent.client.ps.gunframe = FRAME_IDLE_FIRST;
return;
}
if (pause_frames != null) {
for (n = 0; pause_frames[n] != 0; n++) {
if (ent.client.ps.gunframe == pause_frames[n]) {
if ((Lib.rand() & 15) != 0)
return;
}
}
}
ent.client.ps.gunframe++;
return;
}
}
if (ent.client.weaponstate == Constants.WEAPON_FIRING) {
for (n = 0; fire_frames[n] != 0; n++) {
if (ent.client.ps.gunframe == fire_frames[n]) {
if (ent.client.quad_framenum > GameBase.level.framenum)
ServerGame.PF_StartSound(ent, Constants.CHAN_ITEM, ServerInit.SV_SoundIndex("items/damage3.wav"), (float) 1, (float) Constants.ATTN_NORM,
(float) 0);
fire.think(ent);
break;
}
}
if (0 == fire_frames[n])
ent.client.ps.gunframe++;
if (ent.client.ps.gunframe == FRAME_IDLE_FIRST + 1)
ent.client.weaponstate = Constants.WEAPON_READY;
}
}
/*
* ======================================================================
*
* GRENADE
*
* ======================================================================
*/
public static void weapon_grenade_fire(Entity ent, boolean held) {
float[] offset = { 0, 0, 0 };
float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 };
float[] start = { 0, 0, 0 };
int damage = 125;
float timer;
int speed;
float radius;
radius = damage + 40;
if (is_quad)
damage *= 4;
Math3D.VectorSet(offset, 8, 8, ent.viewheight - 8);
Math3D.AngleVectors(ent.client.v_angle, forward, right, null);
P_ProjectSource(ent.client, ent.s.origin, offset, forward, right, start);
timer = ent.client.grenade_time - GameBase.level.time;
speed = (int) (Constants.GRENADE_MINSPEED + (Constants.GRENADE_TIMER - timer)
* ((Constants.GRENADE_MAXSPEED - Constants.GRENADE_MINSPEED) / Constants.GRENADE_TIMER));
GameWeapon.fire_grenade2(ent, start, forward, damage, speed, timer, radius,
held);
if (0 == ((int) GameBase.dmflags.value & Constants.DF_INFINITE_AMMO))
ent.client.pers.inventory[ent.client.ammo_index]--;
ent.client.grenade_time = GameBase.level.time + 1.0f;
if (ent.deadflag != 0 || ent.s.modelindex != 255) // VWep animations
// screw up corpses
{
return;
}
if (ent.health <= 0)
return;
if ((ent.client.ps.pmove.pm_flags & PlayerMove.PMF_DUCKED) != 0) {
ent.client.anim_priority = Constants.ANIM_ATTACK;
ent.s.frame = MonsterPlayer.FRAME_crattak1 - 1;
ent.client.anim_end = MonsterPlayer.FRAME_crattak3;
} else {
ent.client.anim_priority = Constants.ANIM_REVERSE;
ent.s.frame = MonsterPlayer.FRAME_wave08;
ent.client.anim_end = MonsterPlayer.FRAME_wave01;
}
}
/*
* ======================================================================
*
* BLASTER / HYPERBLASTER
*
* ======================================================================
*/
public static void Blaster_Fire(Entity ent, float[] g_offset, int damage,
boolean hyper, int effect) {
float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 };
float[] start = { 0, 0, 0 };
float[] offset = { 0, 0, 0 };
if (is_quad)
damage *= 4;
Math3D.AngleVectors(ent.client.v_angle, forward, right, null);
Math3D.VectorSet(offset, 24, 8, ent.viewheight - 8);
Math3D.VectorAdd(offset, g_offset, offset);
P_ProjectSource(ent.client, ent.s.origin, offset, forward, right, start);
Math3D.VectorScale(forward, -2, ent.client.kick_origin);
ent.client.kick_angles[0] = -1;
GameWeapon.fire_blaster(ent, start, forward, damage, 1000, effect, hyper);
// send muzzle flash
ServerGame.PF_WriteByte(Constants.svc_muzzleflash);
ServerGame.PF_WriteShort(ent.index);
if (hyper)
ServerGame.PF_WriteByte(Constants.MZ_HYPERBLASTER | is_silenced);
else
ServerGame.PF_WriteByte(Constants.MZ_BLASTER | is_silenced);
ServerSend.SV_Multicast(ent.s.origin, Constants.MULTICAST_PVS);
PlayerWeapon.PlayerNoise(ent, start, Constants.PNOISE_WEAPON);
}
/*
* ===============
* PlayerNoise
*
* Each player can have two noise objects associated with it: a personal
* noise (jumping, pain, weapon firing), and a weapon target noise (bullet
* wall impacts)
*
* Monsters that don't directly see the player can move to a noise in hopes
* of seeing the player from there.
* ===============
*/
static void PlayerNoise(Entity who, float[] where, int type) {
Entity noise;
if (type == Constants.PNOISE_WEAPON) {
if (who.client.silencer_shots > 0) {
who.client.silencer_shots--;
return;
}
}
if (GameBase.deathmatch.value != 0)
return;
if ((who.flags & Constants.FL_NOTARGET) != 0)
return;
if (who.mynoise == null) {
noise = GameUtil.G_Spawn();
noise.classname = "player_noise";
Math3D.VectorSet(noise.mins, -8, -8, -8);
Math3D.VectorSet(noise.maxs, 8, 8, 8);
noise.owner = who;
noise.svflags = Constants.SVF_NOCLIENT;
who.mynoise = noise;
noise = GameUtil.G_Spawn();
noise.classname = "player_noise";
Math3D.VectorSet(noise.mins, -8, -8, -8);
Math3D.VectorSet(noise.maxs, 8, 8, 8);
noise.owner = who;
noise.svflags = Constants.SVF_NOCLIENT;
who.mynoise2 = noise;
}
if (type == Constants.PNOISE_SELF || type == Constants.PNOISE_WEAPON) {
noise = who.mynoise;
GameBase.level.sound_entity = noise;
GameBase.level.sound_entity_framenum = GameBase.level.framenum;
}
else // type == PNOISE_IMPACT
{
noise = who.mynoise2;
GameBase.level.sound2_entity = noise;
GameBase.level.sound2_entity_framenum = GameBase.level.framenum;
}
Math3D.VectorCopy(where, noise.s.origin);
Math3D.VectorSubtract(where, noise.maxs, noise.absmin);
Math3D.VectorAdd(where, noise.maxs, noise.absmax);
noise.teleport_time = GameBase.level.time;
World.SV_LinkEdict(noise);
}
}