/** * Cmd_Drop_f * * Drop an inventory item. */ public static void Drop_f(edict_t ent) { int index; gitem_t it; string s; s = Cmd.Args(); it = GameItems.FindItem(s); if (it == null) { SV_GAME.PF_cprintfhigh(ent, "unknown item: " + s + "\n"); return; } if (it.drop == null) { SV_GAME.PF_cprintf(ent, Defines.PRINT_HIGH, "Item is not dropable.\n"); return; } index = GameItems.ITEM_INDEX(it); if (0 == ent.client.pers.inventory[index]) { SV_GAME.PF_cprintfhigh(ent, "Out of item: " + s + "\n"); return; } it.drop.drop(ent, it); }
public static void SP_trigger_key(edict_t self) { if (GameBase.st.item == null) { GameBase.gi.dprintf("no key item for trigger_key at " + Lib.vtos(self.s.origin) + "\n"); return; } self.item = GameItems.FindItemByClassname(GameBase.st.item); if (null == self.item) { GameBase.gi.dprintf("item " + GameBase.st.item + " not found for trigger_key at " + Lib.vtos(self.s.origin) + "\n"); return; } if (self.target == null) { GameBase.gi.dprintf(self.classname + " at " + Lib.vtos(self.s.origin) + " has no target\n"); return; } GameBase.gi.soundindex("misc/keytry.wav"); GameBase.gi.soundindex("misc/keyuse.wav"); self.use = GameTrigger.trigger_key_use; }
/** * Cmd_WeapLast_f. */ public static void WeapLast_f(edict_t ent) { gclient_t cl; int index; gitem_t it; cl = ent.client; if (null == cl.pers.weapon || null == cl.pers.lastweapon) { return; } index = GameItems.ITEM_INDEX(cl.pers.lastweapon); if (0 == cl.pers.inventory[index]) { return; } it = GameItemList.itemlist[index]; if (null == it.use) { return; } if (0 == (it.flags & Defines.IT_WEAPON)) { return; } it.use.use(ent, it); }
private static int CheckArmor(edict_t ent, float[] point, float[] normal, int damage, int te_sparks, int dflags) { gclient_t client; int save; int index; gitem_t armor; if (damage == 0) { return(0); } client = ent.client; if (client == null) { return(0); } if ((dflags & Defines.DAMAGE_NO_ARMOR) != 0) { return(0); } index = GameItems.ArmorIndex(ent); if (index == 0) { return(0); } armor = GameItems.GetItemByIndex(index); var garmor = (gitem_armor_t)armor.info; if (0 != (dflags & Defines.DAMAGE_ENERGY)) { save = (int)Math.Ceiling(garmor.energy_protection * damage); } else { save = (int)Math.Ceiling(garmor.normal_protection * damage); } if (save >= client.pers.inventory[index]) { save = client.pers.inventory[index]; } if (save == 0) { return(0); } client.pers.inventory[index] -= save; GameCombat.SpawnDamage(te_sparks, point, normal, save); return(save); }
/* * =============== * G_SetClientEffects * =============== */ public static void G_SetClientEffects(edict_t ent) { int pa_type; int remaining; ent.s.effects = 0; ent.s.renderfx = 0; if (ent.health <= 0 || GameBase.level.intermissiontime != 0) { return; } if (ent.powerarmor_time > GameBase.level.time) { pa_type = GameItems.PowerArmorType(ent); if (pa_type == Defines.POWER_ARMOR_SCREEN) { ent.s.effects |= Defines.EF_POWERSCREEN; } else if (pa_type == Defines.POWER_ARMOR_SHIELD) { ent.s.effects |= Defines.EF_COLOR_SHELL; ent.s.renderfx |= Defines.RF_SHELL_GREEN; } } if (ent.client.quad_framenum > GameBase.level.framenum) { remaining = (int)ent.client.quad_framenum - GameBase.level.framenum; if (remaining > 30 || 0 != (remaining & 4)) { ent.s.effects |= Defines.EF_QUAD; } } if (ent.client.invincible_framenum > GameBase.level.framenum) { remaining = (int)ent.client.invincible_framenum - GameBase.level.framenum; if (remaining > 30 || 0 != (remaining & 4)) { ent.s.effects |= Defines.EF_PENT; } } // show cheaters!!! if ((ent.flags & Defines.FL_GODMODE) != 0) { ent.s.effects |= Defines.EF_COLOR_SHELL; ent.s.renderfx |= Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE; } }
/** * Cmd_WeapNext_f. */ public static void WeapNext_f(edict_t ent) { gclient_t cl; int i, index; gitem_t it; int selected_weapon; cl = ent.client; if (null == cl.pers.weapon) { return; } selected_weapon = GameItems.ITEM_INDEX(cl.pers.weapon); // scan for the next valid one for (i = 1; i <= Defines.MAX_ITEMS; i++) { index = (selected_weapon + Defines.MAX_ITEMS - i) % Defines.MAX_ITEMS; //bugfix rst if (index == 0) { index++; } if (0 == cl.pers.inventory[index]) { continue; } it = GameItemList.itemlist[index]; if (null == it.use) { continue; } if (0 == (it.flags & Defines.IT_WEAPON)) { continue; } it.use.use(ent, it); if (cl.pers.weapon == it) { return; // successful } } }
public static void SP_turret_driver(edict_t self) { if (GameBase.deathmatch.value != 0) { GameUtil.G_FreeEdict(self); return; } self.movetype = Defines.MOVETYPE_PUSH; self.solid = Defines.SOLID_BBOX; self.s.modelindex = GameBase.gi.modelindex("models/monsters/infantry/tris.md2"); Math3D.VectorSet(self.mins, -16, -16, -24); Math3D.VectorSet(self.maxs, 16, 16, 32); self.health = 100; self.gib_health = 0; self.mass = 200; self.viewheight = 24; self.die = GameTurret.turret_driver_die; self.monsterinfo.stand = M_Infantry.infantry_stand; self.flags |= Defines.FL_NO_KNOCKBACK; GameBase.level.total_monsters++; self.svflags |= Defines.SVF_MONSTER; self.s.renderfx |= Defines.RF_FRAMELERP; self.takedamage = Defines.DAMAGE_AIM; self.use = GameUtil.monster_use; self.clipmask = Defines.MASK_MONSTERSOLID; Math3D.VectorCopy(self.s.origin, self.s.old_origin); self.monsterinfo.aiflags |= Defines.AI_STAND_GROUND | Defines.AI_DUCKED; if (GameBase.st.item != null) { self.item = GameItems.FindItemByClassname(GameBase.st.item); if (self.item == null) { GameBase.gi.dprintf(self.classname + " at " + Lib.vtos(self.s.origin) + " has bad item: " + GameBase.st.item + "\n"); } } self.think = GameTurret.turret_driver_link; self.nextthink = GameBase.level.time + Defines.FRAMETIME; GameBase.gi.linkentity(self); }
/* * ================ monster_death_use * * When a monster dies, it fires all of its targets with the current enemy * as activator. ================ */ public static void monster_death_use(edict_t self) { self.flags &= ~(Defines.FL_FLY | Defines.FL_SWIM); self.monsterinfo.aiflags &= Defines.AI_GOOD_GUY; if (self.item != null) { GameItems.Drop_Item(self, self.item); self.item = null; } if (self.deathtarget != null) { self.target = self.deathtarget; } if (self.target == null) { return; } GameUtil.G_UseTargets(self, self.enemy); }
/** * Cmd_Use_f * * Use an inventory item. */ public static void Use_f(edict_t ent) { int index; gitem_t it; string s; s = Cmd.Args(); it = GameItems.FindItem(s); Com.dprintln("using:" + s); if (it == null) { SV_GAME.PF_cprintfhigh(ent, "unknown item: " + s + "\n"); return; } if (it.use == null) { SV_GAME.PF_cprintfhigh(ent, "Item is not usable.\n"); return; } index = GameItems.ITEM_INDEX(it); if (0 == ent.client.pers.inventory[index]) { SV_GAME.PF_cprintfhigh(ent, "Out of item: " + s + "\n"); return; } it.use.use(ent, it); }
/** * InitGame * * This will be called when the dll is first loaded, which only happens when * a new game is started or a save game is loaded. */ public static void InitGame() { GameBase.gi.dprintf("==== InitGame ====\n"); // preload all classes to register the adapters for (var n = 0; n < GameSave.preloadclasslist.Length; n++) { try { RuntimeHelpers.RunClassConstructor(GameSave.preloadclasslist[n].TypeHandle); } catch (Exception) { Com.DPrintf("error loading class: " + GameSave.preloadclasslist[n]); } } GameBase.gun_x = GameBase.gi.cvar("gun_x", "0", 0); GameBase.gun_y = GameBase.gi.cvar("gun_y", "0", 0); GameBase.gun_z = GameBase.gi.cvar("gun_z", "0", 0); //FIXME: sv_ prefix are wrong names for these variables GameBase.sv_rollspeed = GameBase.gi.cvar("sv_rollspeed", "200", 0); GameBase.sv_rollangle = GameBase.gi.cvar("sv_rollangle", "2", 0); GameBase.sv_maxvelocity = GameBase.gi.cvar("sv_maxvelocity", "2000", 0); GameBase.sv_gravity = GameBase.gi.cvar("sv_gravity", "800", 0); // noset vars Globals.dedicated = GameBase.gi.cvar("dedicated", "0", Defines.CVAR_NOSET); // latched vars GameBase.sv_cheats = GameBase.gi.cvar("cheats", "0", Defines.CVAR_SERVERINFO | Defines.CVAR_LATCH); GameBase.gi.cvar("gamename", Defines.GAMEVERSION, Defines.CVAR_SERVERINFO | Defines.CVAR_LATCH); GameBase.gi.cvar("gamedate", Globals.__DATE__, Defines.CVAR_SERVERINFO | Defines.CVAR_LATCH); GameBase.maxclients = GameBase.gi.cvar("maxclients", "4", Defines.CVAR_SERVERINFO | Defines.CVAR_LATCH); GameBase.maxspectators = GameBase.gi.cvar("maxspectators", "4", Defines.CVAR_SERVERINFO); GameBase.deathmatch = GameBase.gi.cvar("deathmatch", "0", Defines.CVAR_LATCH); GameBase.coop = GameBase.gi.cvar("coop", "0", Defines.CVAR_LATCH); GameBase.skill = GameBase.gi.cvar("skill", "0", Defines.CVAR_LATCH); GameBase.maxentities = GameBase.gi.cvar("maxentities", "1024", Defines.CVAR_LATCH); // change anytime vars GameBase.dmflags = GameBase.gi.cvar("dmflags", "0", Defines.CVAR_SERVERINFO); GameBase.fraglimit = GameBase.gi.cvar("fraglimit", "0", Defines.CVAR_SERVERINFO); GameBase.timelimit = GameBase.gi.cvar("timelimit", "0", Defines.CVAR_SERVERINFO); GameBase.password = GameBase.gi.cvar("password", "", Defines.CVAR_USERINFO); GameBase.spectator_password = GameBase.gi.cvar("spectator_password", "", Defines.CVAR_USERINFO); GameBase.needpass = GameBase.gi.cvar("needpass", "0", Defines.CVAR_SERVERINFO); GameBase.filterban = GameBase.gi.cvar("filterban", "1", 0); GameBase.g_select_empty = GameBase.gi.cvar("g_select_empty", "0", Defines.CVAR_ARCHIVE); GameBase.run_pitch = GameBase.gi.cvar("run_pitch", "0.002", 0); GameBase.run_roll = GameBase.gi.cvar("run_roll", "0.005", 0); GameBase.bob_up = GameBase.gi.cvar("bob_up", "0.005", 0); GameBase.bob_pitch = GameBase.gi.cvar("bob_pitch", "0.002", 0); GameBase.bob_roll = GameBase.gi.cvar("bob_roll", "0.002", 0); // flood control GameBase.flood_msgs = GameBase.gi.cvar("flood_msgs", "4", 0); GameBase.flood_persecond = GameBase.gi.cvar("flood_persecond", "4", 0); GameBase.flood_waitdelay = GameBase.gi.cvar("flood_waitdelay", "10", 0); // dm map list GameBase.sv_maplist = GameBase.gi.cvar("sv_maplist", "", 0); // items GameItems.InitItems(); GameBase.game.helpmessage1 = ""; GameBase.game.helpmessage2 = ""; // initialize all entities for this game GameBase.game.maxentities = (int)GameBase.maxentities.value; GameSave.CreateEdicts(); // initialize all clients for this game GameBase.game.maxclients = (int)GameBase.maxclients.value; GameSave.CreateClients(); GameBase.num_edicts = GameBase.game.maxclients + 1; }
//======================================================================= /* * =============== * G_SetStats * =============== */ public static void G_SetStats(edict_t ent) { gitem_t item; int index, cells = 0; int power_armor_type; // // health // ent.client.ps.stats[Defines.STAT_HEALTH_ICON] = (short)GameBase.level.pic_health; ent.client.ps.stats[Defines.STAT_HEALTH] = (short)ent.health; // // ammo // if (0 == ent.client.ammo_index /* * || * !ent.client.pers.inventory[ent.client.ammo_index] */ ) { ent.client.ps.stats[Defines.STAT_AMMO_ICON] = 0; ent.client.ps.stats[Defines.STAT_AMMO] = 0; } else { item = GameItemList.itemlist[ent.client.ammo_index]; ent.client.ps.stats[Defines.STAT_AMMO_ICON] = (short)GameBase.gi.imageindex(item.icon); ent.client.ps.stats[Defines.STAT_AMMO] = (short)ent.client.pers.inventory[ent.client.ammo_index]; } // // armor // power_armor_type = GameItems.PowerArmorType(ent); if (power_armor_type != 0) { cells = ent.client.pers.inventory[GameItems.ITEM_INDEX(GameItems.FindItem("cells"))]; if (cells == 0) { // ran out of cells for power armor ent.flags &= ~Defines.FL_POWER_ARMOR; GameBase.gi.sound(ent, Defines.CHAN_ITEM, GameBase.gi.soundindex("misc/power2.wav"), 1, Defines.ATTN_NORM, 0); power_armor_type = 0; ; } } index = GameItems.ArmorIndex(ent); if (power_armor_type != 0 && (0 == index || 0 != (GameBase.level.framenum & 8))) { // flash // between // power // armor // and // other // armor // icon ent.client.ps.stats[Defines.STAT_ARMOR_ICON] = (short)GameBase.gi.imageindex("i_powershield"); ent.client.ps.stats[Defines.STAT_ARMOR] = (short)cells; } else if (index != 0) { item = GameItems.GetItemByIndex(index); ent.client.ps.stats[Defines.STAT_ARMOR_ICON] = (short)GameBase.gi.imageindex(item.icon); ent.client.ps.stats[Defines.STAT_ARMOR] = (short)ent.client.pers.inventory[index]; } else { ent.client.ps.stats[Defines.STAT_ARMOR_ICON] = 0; ent.client.ps.stats[Defines.STAT_ARMOR] = 0; } // // pickup message // if (GameBase.level.time > ent.client.pickup_msg_time) { ent.client.ps.stats[Defines.STAT_PICKUP_ICON] = 0; ent.client.ps.stats[Defines.STAT_PICKUP_STRING] = 0; } // // timers // if (ent.client.quad_framenum > GameBase.level.framenum) { ent.client.ps.stats[Defines.STAT_TIMER_ICON] = (short)GameBase.gi.imageindex("p_quad"); ent.client.ps.stats[Defines.STAT_TIMER] = (short)((ent.client.quad_framenum - GameBase.level.framenum) / 10); } else if (ent.client.invincible_framenum > GameBase.level.framenum) { ent.client.ps.stats[Defines.STAT_TIMER_ICON] = (short)GameBase.gi.imageindex("p_invulnerability"); ent.client.ps.stats[Defines.STAT_TIMER] = (short)((ent.client.invincible_framenum - GameBase.level.framenum) / 10); } else if (ent.client.enviro_framenum > GameBase.level.framenum) { ent.client.ps.stats[Defines.STAT_TIMER_ICON] = (short)GameBase.gi.imageindex("p_envirosuit"); ent.client.ps.stats[Defines.STAT_TIMER] = (short)((ent.client.enviro_framenum - GameBase.level.framenum) / 10); } else if (ent.client.breather_framenum > GameBase.level.framenum) { ent.client.ps.stats[Defines.STAT_TIMER_ICON] = (short)GameBase.gi.imageindex("p_rebreather"); ent.client.ps.stats[Defines.STAT_TIMER] = (short)((ent.client.breather_framenum - GameBase.level.framenum) / 10); } else { ent.client.ps.stats[Defines.STAT_TIMER_ICON] = 0; ent.client.ps.stats[Defines.STAT_TIMER] = 0; } // // selected item // // bugfix rst if (ent.client.pers.selected_item <= 0) { ent.client.ps.stats[Defines.STAT_SELECTED_ICON] = 0; } else { ent.client.ps.stats[Defines.STAT_SELECTED_ICON] = (short)GameBase.gi.imageindex(GameItemList.itemlist[ent.client.pers.selected_item].icon); } ent.client.ps.stats[Defines.STAT_SELECTED_ITEM] = (short)ent.client.pers.selected_item; // // layouts // ent.client.ps.stats[Defines.STAT_LAYOUTS] = 0; if (GameBase.deathmatch.value != 0) { if (ent.client.pers.health <= 0 || GameBase.level.intermissiontime != 0 || ent.client.showscores) { ent.client.ps.stats[Defines.STAT_LAYOUTS] |= 1; } if (ent.client.showinventory && ent.client.pers.health > 0) { ent.client.ps.stats[Defines.STAT_LAYOUTS] |= 2; } } else { if (ent.client.showscores || ent.client.showhelp) { ent.client.ps.stats[Defines.STAT_LAYOUTS] |= 1; } if (ent.client.showinventory && ent.client.pers.health > 0) { ent.client.ps.stats[Defines.STAT_LAYOUTS] |= 2; } } // // frags // ent.client.ps.stats[Defines.STAT_FRAGS] = (short)ent.client.resp.score; // // help icon / current weapon if not shown // if (ent.client.pers.helpchanged != 0 && (GameBase.level.framenum & 8) != 0) { ent.client.ps.stats[Defines.STAT_HELPICON] = (short)GameBase.gi.imageindex("i_help"); } else if ((ent.client.pers.hand == Defines.CENTER_HANDED || ent.client.ps.fov > 91) && ent.client.pers.weapon != null) { ent.client.ps.stats[Defines.STAT_HELPICON] = (short)GameBase.gi.imageindex(ent.client.pers.weapon.icon); } else { ent.client.ps.stats[Defines.STAT_HELPICON] = 0; } ent.client.ps.stats[Defines.STAT_SPECTATOR] = 0; }
/** * Cmd_Give_f * * Give items to a client. */ public static void Give_f(edict_t ent) { string name; gitem_t it; int index; int i; bool give_all; edict_t it_ent; if (GameBase.deathmatch.value != 0 && GameBase.sv_cheats.value == 0) { SV_GAME.PF_cprintfhigh(ent, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } name = Cmd.Args(); if (0 == Lib.Q_stricmp(name, "all")) { give_all = true; } else { give_all = false; } if (give_all || 0 == Lib.Q_stricmp(Cmd.Argv(1), "health")) { if (Cmd.Argc() == 3) { ent.health = Lib.atoi(Cmd.Argv(2)); } else { ent.health = ent.max_health; } if (!give_all) { return; } } if (give_all || 0 == Lib.Q_stricmp(name, "weapons")) { for (i = 1; i < GameBase.game.num_items; i++) { it = GameItemList.itemlist[i]; if (null == it.pickup) { continue; } if (0 == (it.flags & Defines.IT_WEAPON)) { continue; } ent.client.pers.inventory[i] += 1; } if (!give_all) { return; } } if (give_all || 0 == Lib.Q_stricmp(name, "ammo")) { for (i = 1; i < GameBase.game.num_items; i++) { it = GameItemList.itemlist[i]; if (null == it.pickup) { continue; } if (0 == (it.flags & Defines.IT_AMMO)) { continue; } GameItems.Add_Ammo(ent, it, 1000); } if (!give_all) { return; } } if (give_all || Lib.Q_stricmp(name, "armor") == 0) { gitem_armor_t info; it = GameItems.FindItem("Jacket Armor"); ent.client.pers.inventory[GameItems.ITEM_INDEX(it)] = 0; it = GameItems.FindItem("Combat Armor"); ent.client.pers.inventory[GameItems.ITEM_INDEX(it)] = 0; it = GameItems.FindItem("Body Armor"); info = (gitem_armor_t)it.info; ent.client.pers.inventory[GameItems.ITEM_INDEX(it)] = info.max_count; if (!give_all) { return; } } if (give_all || Lib.Q_stricmp(name, "Power Shield") == 0) { it = GameItems.FindItem("Power Shield"); it_ent = GameUtil.G_Spawn(); it_ent.classname = it.classname; GameItems.SpawnItem(it_ent, it); GameItems.Touch_Item.touch(it_ent, ent, GameBase.dummyplane, null); if (it_ent.inuse) { GameUtil.G_FreeEdict(it_ent); } if (!give_all) { return; } } if (give_all) { for (i = 1; i < GameBase.game.num_items; i++) { it = GameItemList.itemlist[i]; if (it.pickup != null) { continue; } if ((it.flags & (Defines.IT_ARMOR | Defines.IT_WEAPON | Defines.IT_AMMO)) != 0) { continue; } ent.client.pers.inventory[i] = 1; } return; } it = GameItems.FindItem(name); if (it == null) { name = Cmd.Argv(1); it = GameItems.FindItem(name); if (it == null) { SV_GAME.PF_cprintf(ent, Defines.PRINT_HIGH, "unknown item\n"); return; } } if (it.pickup == null) { SV_GAME.PF_cprintf(ent, Defines.PRINT_HIGH, "non-pickup item\n"); return; } index = GameItems.ITEM_INDEX(it); if ((it.flags & Defines.IT_AMMO) != 0) { if (Cmd.Argc() == 3) { ent.client.pers.inventory[index] = Lib.atoi(Cmd.Argv(2)); } else { ent.client.pers.inventory[index] += it.quantity; } } else { it_ent = GameUtil.G_Spawn(); it_ent.classname = it.classname; GameItems.SpawnItem(it_ent, it); GameItems.Touch_Item.touch(it_ent, ent, GameBase.dummyplane, null); if (it_ent.inuse) { GameUtil.G_FreeEdict(it_ent); } } }
// ============================================================================ public static bool monster_start(edict_t self) { if (GameBase.deathmatch.value != 0) { GameUtil.G_FreeEdict(self); return(false); } if ((self.spawnflags & 4) != 0 && 0 == (self.monsterinfo.aiflags & Defines.AI_GOOD_GUY)) { self.spawnflags &= ~4; self.spawnflags |= 1; // gi.dprintf("fixed spawnflags on %s at %s\n", self.classname, // vtos(self.s.origin)); } if (0 == (self.monsterinfo.aiflags & Defines.AI_GOOD_GUY)) { GameBase.level.total_monsters++; } self.nextthink = GameBase.level.time + Defines.FRAMETIME; self.svflags |= Defines.SVF_MONSTER; self.s.renderfx |= Defines.RF_FRAMELERP; self.takedamage = Defines.DAMAGE_AIM; self.air_finished = GameBase.level.time + 12; self.use = GameUtil.monster_use; self.max_health = self.health; self.clipmask = Defines.MASK_MONSTERSOLID; self.s.skinnum = 0; self.deadflag = Defines.DEAD_NO; self.svflags &= ~Defines.SVF_DEADMONSTER; if (null == self.monsterinfo.checkattack) { self.monsterinfo.checkattack = GameUtil.M_CheckAttack; } Math3D.VectorCopy(self.s.origin, self.s.old_origin); if (GameBase.st.item != null && GameBase.st.item.Length > 0) { self.item = GameItems.FindItemByClassname(GameBase.st.item); if (self.item == null) { GameBase.gi.dprintf("monster_start:" + self.classname + " at " + Lib.vtos(self.s.origin) + " has bad item: " + GameBase.st.item + "\n"); } } // randomize what frame they start on if (self.monsterinfo.currentmove != null) { self.s.frame = self.monsterinfo.currentmove.firstframe + Lib.rand() % (self.monsterinfo.currentmove.lastframe - self.monsterinfo.currentmove.firstframe + 1); } return(true); }
private static int CheckPowerArmor(edict_t ent, float[] point, float[] normal, int damage, int dflags) { gclient_t client; int save; int power_armor_type; var index = 0; int damagePerCell; int pa_te_type; var power = 0; int power_used; if (damage == 0) { return(0); } client = ent.client; if ((dflags & Defines.DAMAGE_NO_ARMOR) != 0) { return(0); } if (client != null) { power_armor_type = GameItems.PowerArmorType(ent); if (power_armor_type != Defines.POWER_ARMOR_NONE) { index = GameItems.ITEM_INDEX(GameItems.FindItem("Cells")); power = client.pers.inventory[index]; } } else if ((ent.svflags & Defines.SVF_MONSTER) != 0) { power_armor_type = ent.monsterinfo.power_armor_type; power = ent.monsterinfo.power_armor_power; } else { return(0); } if (power_armor_type == Defines.POWER_ARMOR_NONE) { return(0); } if (power == 0) { return(0); } if (power_armor_type == Defines.POWER_ARMOR_SCREEN) { float[] vec = { 0, 0, 0 }; float dot; float[] forward = { 0, 0, 0 }; // only works if damage point is in front Math3D.AngleVectors(ent.s.angles, forward, null, null); Math3D.VectorSubtract(point, ent.s.origin, vec); Math3D.VectorNormalize(vec); dot = Math3D.DotProduct(vec, forward); if (dot <= 0.3) { return(0); } damagePerCell = 1; pa_te_type = Defines.TE_SCREEN_SPARKS; damage = damage / 3; } else { damagePerCell = 2; pa_te_type = Defines.TE_SHIELD_SPARKS; damage = 2 * damage / 3; } save = power * damagePerCell; if (save == 0) { return(0); } if (save > damage) { save = damage; } GameCombat.SpawnDamage(pa_te_type, point, normal, save); ent.powerarmor_time = GameBase.level.time + 0.2f; power_used = save / damagePerCell; if (client != null) { client.pers.inventory[index] -= power_used; } else { ent.monsterinfo.power_armor_power -= power_used; } return(save); }