#endif
#ifdef CSQC
-<<<<<<< HEAD
-#include <client/hud/hud.qh>
-
-//Inventory g_inventory;
-Inventory inventoryslots[255];
-float last_pickup_timer;
-entity last_pickup_item;
-int last_pickup_times;
-NET_HANDLE(ENT_CLIENT_INVENTORY, bool isnew)
-{
- make_pure(this);
- //g_inventory = this;
-
- float entnum = ReadByte() - 1;
- inventoryslots[entnum] = this;
-
-=======
Inventory g_inventory;
void Inventory_remove(entity this)
{
make_pure(this);
g_inventory = this;
this.entremove = Inventory_remove;
->>>>>>> master
const int majorBits = Readbits(Inventory_groups_major);
for (int i = 0; i < Inventory_groups_major; ++i) {
if (!(majorBits & BIT(i))) {
.int fld = inv_items[it.m_id];
int prev = this.(fld);
int next = this.(fld) = ReadByte();
-
- if(entnum == current_player) {
- if(last_pickup_item != it) last_pickup_times = 0;
- last_pickup_timer = timer;
- last_pickup_item = it;
- last_pickup_times++;
- }
-
LOG_DEBUGF("%s: %.0f -> %.0f", it.m_name, prev, next);
}
}
return true;
}
-
-NET_HANDLE(TE_CSQC_WEAPONPICKUP, bool isnew)
-{
- const Weapon it = REGISTRY_GET(Weapons, ReadByte());
-
- if(last_pickup_item != it) last_pickup_times = 0;
- last_pickup_timer = timer;
- last_pickup_item = it;
- last_pickup_times++;
-
- return true;
-}
#endif
#ifdef SVQC
void Inventory_new(PlayerState this)
{
Inventory inv = NEW(Inventory);
- if(!g_duel) setcefc(inv, Inventory_customize);
+ setcefc(inv, Inventory_customize);
Net_LinkEntity((inv.owner = this).inventory = inv, false, 0, Inventory_Send);
}
void Inventory_delete(entity e) { delete(e.inventory); }
}
void InventoryStorage_attach(entity e) { e.inventory_store = NEW(Inventory); e.inventory_store.drawonlytoclient = e; }
-<<<<<<< HEAD
-void InventoryStorage_detach(entity e) { delete(e.inventory_store); }
-
-void Inventory_ClearAll() {
- FOREACH_CLIENT(IS_PLAYER(it), {
- entity store = PS(it);
- FOREACH(Items, true, {
- store.inventory.inv_items[it.m_id] = 0;
- });
- Inventory_update(store);
- });
-}
-=======
void InventoryStorage_delete(entity e) { delete(e.inventory_store); }
->>>>>>> master
#endif
#include <common/effects/all.qh>
+//LegendGuard adds purple nade parts 08-02-2021
+//LegendGuard adds green nade parts 11-02-2021
EFFECT(0, NADE_EXPLODE_RED, "nade_red_explode")
EFFECT(0, NADE_EXPLODE_BLUE, "nade_blue_explode")
EFFECT(0, NADE_EXPLODE_YELLOW, "nade_yellow_explode")
EFFECT(0, NADE_EXPLODE_PINK, "nade_pink_explode")
EFFECT(0, NADE_EXPLODE_NEUTRAL, "nade_neutral_explode")
+EFFECT(0, NADE_EXPLODE_GREEN, "nade_green_explode")
+EFFECT(0, NADE_EXPLODE_PURPLE, "nade_purple_explode")
+
entity EFFECT_NADE_EXPLODE(int teamid)
{
switch (teamid) {
EFFECT(1, NADE_TRAIL_YELLOW, "nade_yellow")
EFFECT(1, NADE_TRAIL_PINK, "nade_pink")
EFFECT(1, NADE_TRAIL_NEUTRAL, "nade_neutral")
+EFFECT(1, NADE_TRAIL_GREEN, "nade_green")
+EFFECT(1, NADE_TRAIL_PURPLE, "nade_purple")
entity EFFECT_NADE_TRAIL(int teamid)
{
switch (teamid) {
EFFECT(1, NADE_TRAIL_BURN_YELLOW, "nade_yellow_burn")
EFFECT(1, NADE_TRAIL_BURN_PINK, "nade_pink_burn")
EFFECT(1, NADE_TRAIL_BURN_NEUTRAL, "nade_neutral_burn")
+EFFECT(1, NADE_TRAIL_BURN_GREEN, "nade_green_burn")
+EFFECT(1, NADE_TRAIL_BURN_PURPLE, "nade_purple_burn")
entity EFFECT_NADE_TRAIL_BURN(int teamid)
{
switch (teamid) {
NADE_PROJECTILE(1, PROJECTILE_NADE_VEIL_BURN, EFFECT_NADE_TRAIL_BURN_NEUTRAL);
#endif
}
+
+//LegendGuard writes Armorize nade code 11-02-2021
+REGISTER_NADE(ARMORIZE) {
+ this.m_color = '0.33 1 0.66';
+ this.m_name = _("Armorize grenade");
+ this.m_icon = "nade_armorize";
+#ifdef GAMEQC
+ NADE_PROJECTILE(0, PROJECTILE_NADE_ARMORIZE, EFFECT_NADE_TRAIL_GREEN);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_ARMORIZE_BURN, EFFECT_NADE_TRAIL_BURN_GREEN);
+#endif
+}
+
+//LegendGuard writes Dark nade code 08-02-2021
+REGISTER_NADE(DARK) {
+ this.m_color = '0.23 0 0.23';
+ this.m_name = _("Dark grenade");
+ this.m_icon = "nade_dark";
+#ifdef GAMEQC
+ NADE_PROJECTILE(0, PROJECTILE_NADE_DARK, EFFECT_NADE_TRAIL_PURPLE);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_DARK_BURN, EFFECT_NADE_TRAIL_BURN_PURPLE);
+#endif
+}
\ No newline at end of file
M_ARGV(1, float) = STAT(VEIL_ORB_ALPHA);
return true;
}
+ if (STAT(ARMORIZING_ORB) > time) //LegendGuard adds new nade STAT ORB (keep in mind: qcsrc/common/stats.qh) 11-02-2021
+ {
+ M_ARGV(0, vector) = NADE_TYPE_ARMORIZE.m_color;
+ M_ARGV(1, float) = STAT(ARMORIZING_ORB_ALPHA);
+ return true;
+ }
+ if (STAT(DARK_ORB) > time) //LegendGuard adds new nade STAT ORB (keep in mind: qcsrc/common/stats.qh) 08-02-2021
+ {
+ M_ARGV(0, vector) = NADE_TYPE_DARK.m_color;
+ M_ARGV(1, float) = STAT(DARK_ORB_ALPHA);
+ return true;
+ }
return false;
}
MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile)
settouch(orb, nade_veil_touch);
orb.colormod = NADE_TYPE_VEIL.m_color;
}
+/**************LEGENDGUARD NEW NADES: ARMORIZE AND DARK NADES functions "cl_nade_type 10" and "cl_nade_type 11" *** //more ideas: BLOCKING NADE ***********************/
+void nade_armorize_touch(entity this, entity toucher)
+{
+ float maxarmor;
+ float maxhealth;
+ float armor_factor;
+ float health_foemantain;
+ float health_maintaining = 1;
+ if(IS_PLAYER(toucher) || IS_MONSTER(toucher))
+ if(!IS_DEAD(toucher))
+ if(!STAT(FROZEN, toucher))
+ {
+ armor_factor = autocvar_g_nades_armorize_rate*frametime/2;
+ health_foemantain = autocvar_g_nades_armorize_rate*frametime/2;
+ if ( toucher != this.realowner )
+ {
+ if ( SAME_TEAM(toucher,this) )
+ {
+ armor_factor *= autocvar_g_nades_armorize_friend;
+ }
+ else
+ {
+ //maintain foe health and reduce armor
+ armor_factor *= autocvar_g_nades_armorize_foe;
+ if (autocvar_g_nades_armorize_friend > 1 || autocvar_g_nades_armorize_friend < 1)
+ health_foemantain *= health_maintaining;
+ else
+ health_foemantain *= autocvar_g_nades_armorize_friend;
+ }
+ }
+ if ( armor_factor > 0 )
+ {
+ maxarmor = 200;
+ float ar = GetResource(toucher, RES_ARMOR);
+ if (ar < maxarmor)
+ {
+ if (this.nade_show_particles)
+ {
+ Send_Effect(EFFECT_HEALING, toucher.origin, '0 0 0', 1);
+ }
+ GiveResourceWithLimit(toucher, RES_ARMOR, armor_factor, maxarmor);
+ }
+ }
+ else if ( armor_factor < 0 )
+ {
+ //Foe should drop only armor points
+ maxhealth = (IS_MONSTER(toucher)) ? toucher.max_health : g_pickup_healthmega_max;
+ float hp = GetResource(toucher, RES_HEALTH);
+ if (hp < maxhealth)
+ {
+ if ((GetResource(toucher, RES_ARMOR) <= 0) && (GetResource(toucher, RES_HEALTH) <= 9999))
+ return;
+ else
+ GiveResourceWithLimit(toucher, RES_HEALTH, health_foemantain/1.3, maxhealth);
+ Damage(toucher,this,this.realowner,-armor_factor,DEATH_NADE_HEAL.m_id,DMG_NOWEP,toucher.origin,'0 0 0');
+ }
+ }
+ }
+
+ if ( IS_REAL_CLIENT(toucher) || IS_VEHICLE(toucher) )
+ {
+ entity show_green = (IS_VEHICLE(toucher)) ? toucher.owner : toucher;
+ STAT(ARMORIZING_ORB, show_green) = time+0.1;
+ STAT(ARMORIZING_ORB_ALPHA, show_green) = 0.75 * (this.ltime - time) / this.orb_lifetime;
+ }
+}
+
+void nade_armorize_boom(entity this)
+{
+ entity orb = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_armorize_time, autocvar_g_nades_nade_radius);
+
+ settouch(orb, nade_armorize_touch);
+ orb.colormod = '0.33 1 0.66';
+}
+/***********************************************************************************/
+//remember to put an image in gfx/hud/luma and gfx/hud/default per each nade_blabla.tga
+//dark nade does damage like a normal nade but the damage is minor
+void dark_damage(entity this, float radius, float damage)
+{
+ entity e;
+
+ if ( damage < 0 )
+ return;
+
+ for(e = WarpZone_FindRadius(this.origin, radius, true); e; e = e.chain)
+ if(!IS_DEAD(e))
+ if(e.takedamage == DAMAGE_AIM)
+ if(!IS_PLAYER(e) || !this.realowner || DIFF_TEAM(e, this) || !IS_MONSTER(e))
+ if(!STAT(FROZEN, e))
+ {
+ RadiusDamage(this, this.realowner, damage, 0,
+ radius, this, NULL, 0, this.projectiledeathtype, DMG_NOWEP, this.enemy);
+ Damage_DamageInfo(this.origin, damage, 0,
+ radius, '1 1 1' * 0, this.projectiledeathtype, 0, this);
+ }
+}
+void DarkBlinking(entity e);
+//copy of the special.qc function contents for DarkBlinking
+void nade_dark_touch(entity this, entity toucher)
+{
+ if ( IS_REAL_CLIENT(toucher) || IS_VEHICLE(toucher) || IS_MONSTER(toucher) )
+ {
+ entity show_tint = (IS_VEHICLE(toucher)) ? toucher.owner : toucher;
+
+ float tint_alpha = 0.55;
+ if(SAME_TEAM(toucher, this.realowner) || SAME_TEAM(toucher, this))
+ {
+ tint_alpha = 0.25;
+ if(!STAT(DARK_ORB, show_tint))
+ {
+ toucher.nade_veil_prevalpha = toucher.alpha;
+ toucher.alpha = 1;
+ }
+ }
+ else
+ {
+ tint_alpha = 0.25;
+ if(!STAT(DARK_ORB, show_tint))
+ {
+ DarkBlinking(toucher);
+ dark_damage(this, autocvar_g_nades_dark_radius, autocvar_g_nades_dark_damage);
+ }
+ }
+ STAT(DARK_ORB, show_tint) = time + 0.1;
+ STAT(DARK_ORB_ALPHA, show_tint) = tint_alpha * (this.ltime - time) / this.orb_lifetime;
+ }
+}
+
+void nade_dark_boom(entity this)
+{
+ entity orb = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_dark_time, autocvar_g_nades_dark_radius);
+
+ settouch(orb, nade_dark_touch);
+ orb.colormod = NADE_TYPE_DARK.m_color;
+}
+/***********************************************************************************/
void nade_boom(entity this)
{
entity expef = NULL;
nade_blast = false;
expef = EFFECT_SPAWN_NEUTRAL;
break;
+
+ case NADE_TYPE_ARMORIZE: //LegendGuard adds nade case 11-02-2021
+ nade_blast = false;
+ expef = EFFECT_SPAWN_NEUTRAL;
+ break;
+
+ case NADE_TYPE_DARK: //LegendGuard adds nade case 08-02-2021
+ nade_blast = false;
+ expef = EFFECT_EXPLOSION_MEDIUM;
+ break;
default:
case NADE_TYPE_NORMAL:
case NADE_TYPE_MONSTER: nade_monster_boom(this); break;
case NADE_TYPE_ENTRAP: nade_entrap_boom(this); break;
case NADE_TYPE_VEIL: nade_veil_boom(this); break;
+ case NADE_TYPE_ARMORIZE: nade_armorize_boom(this); break; //LegendGuard adds the register of new nade 11-02-2021
+ case NADE_TYPE_DARK: nade_dark_boom(this); break; //LegendGuard adds the register of new nade 08-02-2021
}
IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
else
player.alpha = player.nade_veil_prevalpha;
}
+ //LegendGuard adds nade if STAT DARK_ORB 08-02-2021
+ if(STAT(DARK_ORB, player) && STAT(DARK_ORB, player) <= time)
+ {
+ STAT(DARK_ORB, player) = 0;
+ if(player.vehicle)
+ player.vehicle.alpha = player.vehicle.nade_dark_prevalpha;
+ else
+ player.alpha = player.nade_dark_prevalpha;
+ }
}
if (frametime && IS_PLAYER(player))
mon.alpha = mon.nade_veil_prevalpha;
STAT(VEIL_ORB, mon) = 0;
}
+ //LegendGuard adds nade if STAT ORB 08-02-2021
+ if (STAT(DARK_ORB, mon) && STAT(DARK_ORB, mon) <= time)
+ {
+ mon.alpha = mon.nade_dark_prevalpha;
+ STAT(DARK_ORB, mon) = 0;
+ }
}
MUTATOR_HOOKFUNCTION(nades, PlayerSpawn)
STAT(ENTRAP_ORB_ALPHA, client) = STAT(ENTRAP_ORB_ALPHA, spectatee);
STAT(VEIL_ORB, client) = STAT(VEIL_ORB, spectatee);
STAT(VEIL_ORB_ALPHA, client) = STAT(VEIL_ORB_ALPHA, spectatee);
+ STAT(ARMORIZING_ORB, client) = STAT(ARMORIZING_ORB, spectatee); //LegendGuard adds nade STAT client 11-02-2021
+ STAT(ARMORIZING_ORB_ALPHA, client) = STAT(ARMORIZING_ORB_ALPHA, spectatee);
+ STAT(DARK_ORB, client) = STAT(DARK_ORB, spectatee); //LegendGuard adds nade STAT client 08-02-2021
+ STAT(DARK_ORB_ALPHA, client) = STAT(DARK_ORB_ALPHA, spectatee);
}
MUTATOR_HOOKFUNCTION(nades, BuildMutatorsString)
float autocvar_g_nades_entrap_time = 10;
float autocvar_g_nades_veil_time = 8;
float autocvar_g_nades_veil_radius = 300;
+float autocvar_g_nades_armorize_time = 5; //LegendGuard adds new nade cvars 11-02-2021
+float autocvar_g_nades_armorize_rate = 30;
+float autocvar_g_nades_armorize_friend = 1;
+float autocvar_g_nades_armorize_foe = -2;
+float autocvar_g_nades_dark_damage = 25; //LegendGuard adds new nade cvars 08-02-2021
+float autocvar_g_nades_dark_time = 13;
+float autocvar_g_nades_dark_radius = 700;
string autocvar_g_nades_pokenade_monster_type;
float autocvar_g_nades_pokenade_monster_lifetime;
#endif
const int PROJECTILE_NADE_ENTRAP_BURN = 85;
const int PROJECTILE_NADE_VEIL = 86;
const int PROJECTILE_NADE_VEIL_BURN = 87;
+const int PROJECTILE_NADE_ARMORIZE = 88; //LegendGuard adds new nade MACROS 11-02-2021
+const int PROJECTILE_NADE_ARMORIZE_BURN = 89;
+const int PROJECTILE_NADE_DARK = 90; //LegendGuard adds new nade MACROS 08-02-2021
+const int PROJECTILE_NADE_DARK_BURN = 91;
REGISTRY(Nades, BITS(4))
REGISTER_REGISTRY(Nades)
.float toss_time;
.float nade_show_particles;
.float nade_veil_prevalpha;
+.float nade_dark_prevalpha; //LegendGuard adds new nade .variable 08-02-2021
bool orb_send(entity this, entity to, int sf);
#endif
+REGISTER_NET_TEMP(TE_CSQC_DARKBLINKING); //LegendGuard registers dark blinking nade feature 09-02-2021
+
#ifdef CSQC
float cvar_cl_nade_type;
string cvar_cl_pokenade_type;
+//LegendGuard sets variables for dark nade 09-02-2021
+float autocvar_hud_panel_darkradar_maximised_zoom_scale = 1;
+float dark_appeartime;
+float dark_fadetime;
+/***************************************************************/
+void HUD_DarkBlinking()
+{
+ // vectors for top right, bottom right, bottom and bottom left corners
+ //vector topright = vec2(vid_conwidth, 0);
+ //vector bottom = vec2(vid_conwidth / 2, vid_conheight);
+ vector bottomright = vec2(vid_conwidth, vid_conheight);
+ //vector bottomleft = vec2(0, vid_conheight);
+
+ /*
+ drawfill function parameters (qcsrc/dpdefs/menudefs.qc):
+ float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
+ */
+ drawfill('0 0 0', bottomright, '0.23 0 0.23', 0.98, DRAWFLAG_NORMAL);
+}
+
+#elif defined(SVQC)
+void DarkBlinking(entity e)
+{
+ if(e == NULL)
+ return;
+
+ int accepted = VerifyClientEntity(e, true, false);
+
+ if(accepted > 0)
+ {
+ msg_entity = e;
+ WriteHeader(MSG_ONE, TE_CSQC_DARKBLINKING);
+ }
+}
+#endif
+
+#ifdef CSQC
+const int MAX_QUADRATIC2 = 25;
+vector quadratic2_slots[MAX_QUADRATIC2];
+vector quadratic2_dirs[MAX_QUADRATIC2];
+const float QUADRATIC2_SPEED = 150;
+const float QUADRATIC2_TURNSPEED = 0.35;
+const float QUADRATIC2_SIZE = 24;
+const float QUADRATIC2_CHANCE = 0.35;
+float quadratic2_spawntime, quadratic2_fadetime;
+bool quadratic2;
+void HUD_Quadratic2()
+{
+ for(int j = MAX_QUADRATIC2 - 1; j >= 0; --j)
+ {
+ vector slot = quadratic2_slots[j];
+ vector dirs = quadratic2_dirs[j];
+ float oldz = slot.z;
+ if(slot)
+ slot += quadratic2_dirs[j] * QUADRATIC2_SPEED * frametime;
+ slot.z = oldz;
+ //if(slot.z)
+ //slot.z = sin(QUADRATIC2_TURNSPEED * M_PI * time);
+ if(slot.y > vid_conheight || slot.x > vid_conwidth)
+ slot = '0 0 0';
+
+ if(slot == '0 0 0')
+ {
+ if(time > quadratic2_spawntime && random() <= QUADRATIC2_CHANCE) // low chance to spawn!
+ {
+ slot.x = bound(0, (random() * vid_conwidth + 1), vid_conwidth);
+ slot.y = bound(0, (random() * vid_conheight + 1), vid_conheight);
+ slot.z = 0;
+ dirs = vec2(randomvec());
+ quadratic2_spawntime = time + bound(0.05, random() * 0.5, 0.4); // prevent spawning another one for this amount of time!
+ }
+ }
+ else
+ {
+ vector splash_size = vec2(QUADRATIC2_SIZE, QUADRATIC2_SIZE);
+ if(time > dirs.z)
+ {
+ if(random() <= 0.05)
+ slot.z = -1;
+ else
+ slot.z = floor(random() * 9) + 1;
+ dirs.z = time + QUADRATIC2_TURNSPEED;
+ }
+ string chosen_number = ((slot.z == -1) ? "NOOB" : ftos(rint(slot.z)));
+ draw_beginBoldFont();
+ drawcolorcodedstring(vec2(slot), chosen_number, splash_size, 0.95, DRAWFLAG_NORMAL);
+ draw_endBoldFont();
+ }
+
+ quadratic2_slots[j] = slot;
+ quadratic2_dirs[j] = dirs;
+ }
+}
+
+bool darkblink;
+
+STATIC_INIT_LATE(cl_darkblink_override)
+{
+ localcmd("\nalias solve_quadratic2 \"cl_cmd solve_quadratic2 ${* ?}\"\n");
+}
+
+REGISTER_MUTATOR(cl_darkblink, true);
+
+MUTATOR_HOOKFUNCTION(cl_darkblink, DrawScoreboard)
+{
+ return darkblink;
+}
+
+MUTATOR_HOOKFUNCTION(cl_darkblink, HUD_Draw_overlay)
+{
+ if(!darkblink && !quadratic2)
+ return false;
+
+ if(time <= dark_fadetime && autocvar_hud_panel_darkradar_maximised_zoom_scale == 1)
+ {
+ HUD_DarkBlinking();
+ return false;
+ }
+ else
+ darkblink = false;
+
+ if(time <= quadratic2_fadetime)
+ {
+ HUD_Quadratic2();
+ // don't return true, we want regular HUD effects!
+ }
+ else
+ quadratic2 = false;
+
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(cl_darkblink, CSQC_ConsoleCommand)
+{
+ if(MUTATOR_RETURNVALUE) // command was already handled?
+ return;
+
+ string cmd_name = M_ARGV(0, string);
+ //int cmd_argc = M_ARGV(2, int);
+
+ if(cmd_name == "solve_quadratic2")
+ {
+ quadratic2 = true;
+ quadratic2_fadetime = time + 5;
+ return true;
+ }
+}
+
+NET_HANDLE(TE_CSQC_DARKBLINKING, bool isNew)
+{
+ return = true;
+
+ if(darkblink)
+ return;
+
+ localcmd("play2 sound/misc/blind\n");
+ darkblink = true;
+ dark_appeartime = time;
+ dark_fadetime = time + 9;
+}
+#endif
+/***************************************************************/
+#ifdef CSQC
bool Projectile_isnade(int proj); // TODO: remove
void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time); // TODO: mutator
float game_stopped;
float game_starttime; //point in time when the countdown to game start is over
float round_starttime; //point in time when the countdown to round start is over
-float overtime_starttime; // z411 point in time where first overtime started
-
-float checkrules_overtimesadded; // z411 add
-float timeout_last;
-float timeout_total_time;
-bool game_timeout;
-
bool autocvar_g_allow_oldvortexbeam;
int autocvar_leadlimit;
// TODO: world.qh can't be included here due to circular includes!
#endif
REGISTER_STAT(WEAPONRATEFACTOR, float, W_WeaponRateFactor(this))
REGISTER_STAT(GAME_STOPPED, int, game_stopped)
-
-REGISTER_STAT(GAME_TIMEOUT, bool, game_timeout)
-REGISTER_STAT(TIMEOUT_LAST, float, timeout_last)
-
REGISTER_STAT(GAMESTARTTIME, float, game_starttime)
REGISTER_STAT(STRENGTH_FINISHED, float)
REGISTER_STAT(INVINCIBLE_FINISHED, float)
REGISTER_STAT(VEHICLESTAT_RELOAD2, int)
REGISTER_STAT(VEHICLESTAT_W2MODE, int)
REGISTER_STAT(NADE_TIMER, float)
-//REGISTER_STAT(SECRETS_TOTAL, int, secrets_total)
-//REGISTER_STAT(SECRETS_FOUND, int, secrets_found)
+REGISTER_STAT(SECRETS_TOTAL, int, secrets_total)
+REGISTER_STAT(SECRETS_FOUND, int, secrets_found)
REGISTER_STAT(RESPAWN_TIME, float)
REGISTER_STAT(ROUNDSTARTTIME, float, round_starttime)
-REGISTER_STAT(OVERTIMESTARTTIME, float, overtime_starttime)
-REGISTER_STAT(OVERTIMESADDED, float, checkrules_overtimesadded)
-//REGISTER_STAT(MONSTERS_TOTAL, int)
-//REGISTER_STAT(MONSTERS_KILLED, int)
+REGISTER_STAT(MONSTERS_TOTAL, int)
+REGISTER_STAT(MONSTERS_KILLED, int)
REGISTER_STAT(BUFFS, int)
REGISTER_STAT(NADE_BONUS, float)
REGISTER_STAT(NADE_BONUS_TYPE, int)
REGISTER_STAT(KILL_TIME, float)
REGISTER_STAT(VEIL_ORB, float)
REGISTER_STAT(VEIL_ORB_ALPHA, float)
+REGISTER_STAT(ARMORIZING_ORB, float) //LegendGuard registers new STAT 11-02-2021
+REGISTER_STAT(ARMORIZING_ORB_ALPHA, float)
+REGISTER_STAT(DARK_ORB, float) //LegendGuard registers new STAT 08-02-2021
+REGISTER_STAT(DARK_ORB_ALPHA, float)
#ifdef SVQC
float autocvar_sv_showfps = 5;
void W_Devastator_Explode(entity this, entity directhitentity)
{
+
W_Devastator_Unregister(this);
if(directhitentity.takedamage == DAMAGE_AIM)
if(IS_PLAYER(directhitentity))
if(DIFF_TEAM(this.realowner, directhitentity))
if(!IS_DEAD(directhitentity))
- if(IsFlying(directhitentity)) {
- Give_Medal(this.realowner, AIRSHOT);
- }
+ if(IsFlying(directhitentity))
+ Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
this.event_damage = func_null;
this.takedamage = DAMAGE_NO;
vector desireddir, olddir, newdir, desiredorigin, goal;
float velspeed, f;
this.nextthink = time;
- if(game_timeout) { set_movetype(this, MOVETYPE_NONE); this.disableclientprediction = 2; return; } else { set_movetype(this, MOVETYPE_FLY); this.disableclientprediction = 0; }
if(time > this.cnt)
{
this.projectiledeathtype |= HITTYPE_BOUNCE;
UpdateCSQCProjectile(this);
}
+/***************************************/
+//LegendGuard writes homming missile part to test 02-02-2021
+//LegendGuard adds a copy from hk_weapon.qc functions and the EXPERIMENT of homing missile of this weapon worked successfully 07-02-2021
+bool validate_target(entity this, entity proj, entity targ)
+{
+ if (!targ)
+ return false;
+
+ // we know for sure pure entities are bad targets
+ if(is_pure(targ))
+ return false;
+
+ // If only this was used more..
+ if (targ.flags & FL_NOTARGET)
+ return false;
+
+ // Cant touch this
+ if ((targ.takedamage == DAMAGE_NO) || (GetResource(targ, RES_HEALTH) < 0))
+ return false;
+
+ // player
+ if (IS_PLAYER(targ))
+ {
+ if (this.target_select_playerbias < 0)
+ return false;
+
+ if (IS_DEAD(targ))
+ return false;
+ }
+
+ // Missile
+ if ((targ.flags & FL_PROJECTILE) && (this.target_select_missilebias < 0))
+ return false;
+
+ // Team check
+ if (SAME_TEAM(this, targ) || SAME_TEAM(this, targ.owner))
+ return false;
+
+ return true;
+}
+
+void Homing_Missile_Think(entity this)
+{
+ vector vu, vd, vf, vl, vr, ve; // Vector (direction)
+ float fu, fd, ff, fl, fr, fe; // Fraction to solid
+ vector olddir,wishdir,newdir; // Final direction
+ float lt_for; // Length of Trace FORwrad
+ float lt_seek; // Length of Trace SEEK (left, right, up down)
+ float pt_seek; // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
+ float myspeed;
+
+ this.nextthink = time + this.ticrate;
+
+ //if (this.cnt < time)
+ // W_Devastator_Explode();
+
+ if (IS_DEAD(this.enemy) || IS_SPEC(this.enemy) || IS_OBSERVER(this.enemy))
+ this.enemy = NULL;
+
+ // Pick the closest valid target.
+ if (!this.enemy)
+ {
+ // in this case, the lighter check is to validate it first, and check distance if it is valid
+ IL_EACH(g_damagedbycontents, validate_target(this.owner, this, it),
+ {
+ if(vdist(it.origin, >, 5000))
+ continue;
+
+ if(!this.enemy)
+ this.enemy = it;
+ else if(vlen2(this.origin - it.origin) < vlen2(this.origin - this.enemy.origin))
+ this.enemy = it;
+ });
+ }
+
+ this.angles = vectoangles(this.velocity);
+ this.angles_x = this.angles_x * -1;
+ makevectors(this.angles);
+ this.angles_x = this.angles_x * -1;
+
+ if (this.enemy)
+ {
+ // Close enougth to do decent damage?
+ if(vdist(this.origin - this.enemy.origin, <=, (this.owner.shot_radius * 0.25)))
+ {
+ W_Devastator_Explode(this, NULL);
+ return;
+ }
+
+ // Get data on enemy position
+ vector pre_pos = this.enemy.origin +
+ this.enemy.velocity *
+ min((vlen(this.enemy.origin - this.origin) / vlen(this.velocity)),0.5);
+
+ traceline(this.origin, pre_pos,true,this.enemy);
+ ve = normalize(pre_pos - this.origin);
+ fe = trace_fraction;
+
+ }
+ else
+ {
+ ve = '0 0 0';
+ fe = 0;
+ }
+
+ if ((fe != 1) || (this.enemy == NULL) || vdist(this.origin - this.enemy.origin, >, 1000))
+ {
+ myspeed = vlen(this.velocity);
+
+ lt_for = myspeed * 3;
+ lt_seek = myspeed * 2.95;
+
+ // Trace forward
+ traceline(this.origin, this.origin + v_forward * lt_for,false,this);
+ vf = trace_endpos;
+ ff = trace_fraction;
+
+ // Find angular offset
+ float ad = vlen(vectoangles(normalize(this.enemy.origin - this.origin)) - this.angles);
+
+ // To close to something, Slow down!
+ if ( ((ff < 0.7) || (ad > 4)) && (myspeed > WEP_CVAR(devastator, homing_missile_speed)) )
+ myspeed = max(myspeed * WEP_CVAR(devastator, homing_missile_speed_decel), WEP_CVAR(devastator, homing_missile_speed));
+
+ // Failry clear, accelerate.
+ if ( (ff > 0.7) && (myspeed < WEP_CVAR(devastator, homing_missile_speed_max)) )
+ myspeed = min(myspeed * WEP_CVAR(devastator, homing_missile_speed_accel), WEP_CVAR(devastator, homing_missile_speed_max));
+
+ // Setup trace pitch
+ pt_seek = 1 - ff;
+ pt_seek = bound(0.15,pt_seek,0.8);
+ if (ff < 0.5) pt_seek = 1;
+
+ // Trace left
+ traceline(this.origin, this.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,false,this);
+ vl = trace_endpos;
+ fl = trace_fraction;
+
+ // Trace right
+ traceline(this.origin, this.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,false,this);
+ vr = trace_endpos;
+ fr = trace_fraction;
+
+ // Trace up
+ traceline(this.origin, this.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,this);
+ vu = trace_endpos;
+ fu = trace_fraction;
+
+ // Trace down
+ traceline(this.origin, this.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,this);
+ vd = trace_endpos;
+ fd = trace_fraction;
+
+ vl = normalize(vl - this.origin);
+ vr = normalize(vr - this.origin);
+ vu = normalize(vu - this.origin);
+ vd = normalize(vd - this.origin);
+
+ // Panic tresh passed, find a single direction and turn as hard as we can
+ if (pt_seek == 1)
+ {
+ wishdir = v_right;
+ if (fl > fr) wishdir = -1 * v_right;
+ if (fu > fl) wishdir = v_up;
+ if (fd > fu) wishdir = -1 * v_up;
+ }
+ else
+ {
+ // Normalize our trace vectors to make a smooth path
+ wishdir = normalize( (vl * fl) + (vr * fr) + (vu * fu) + (vd * fd) );
+ }
+
+ if (this.enemy)
+ {
+ if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
+ wishdir = (wishdir * (1 - fe)) + (ve * fe);
+ }
+ }
+ else
+ {
+ // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
+ myspeed = vlen(this.velocity);
+ if (myspeed < WEP_CVAR(devastator, homing_missile_speed_max))
+ myspeed = min(myspeed * WEP_CVAR(devastator, homing_missile_speed_accel2), WEP_CVAR(devastator, homing_missile_speed_max));
+
+ wishdir = ve;
+ }
+
+ if ((myspeed > WEP_CVAR(devastator, homing_missile_speed)) && (this.cnt > time))
+ myspeed = min(myspeed * WEP_CVAR(devastator, homing_missile_speed_accel2), WEP_CVAR(devastator, homing_missile_speed_max));
+
+ // Ranoutagazfish?
+ if (this.cnt < time)
+ {
+ this.cnt = time + 0.25;
+ this.nextthink = 0;
+ set_movetype(this, MOVETYPE_BOUNCE);
+ return;
+ }
+
+ // Calculate new heading
+ olddir = normalize(this.velocity);
+ newdir = normalize(olddir + wishdir * WEP_CVAR(devastator, homing_missile_speed_turnrate));
+
+ // Set heading & speed
+ this.velocity = newdir * myspeed;
+
+ // Align model with new heading
+ this.angles = vectoangles(this.velocity);
+
+ UpdateCSQCProjectile(this);
+}
+/********************************/
+
+
void W_Devastator_Touch(entity this, entity toucher)
{
if(WarpZone_Projectile_Touch(this, toucher))
missile.angles = vectoangles(missile.velocity);
settouch(missile, W_Devastator_Touch);
- setthink(missile, W_Devastator_Think);
+
missile.nextthink = time;
+ if(WEP_CVAR(devastator, homing_missile_active) != 0)
+ setthink(missile, Homing_Missile_Think); //LegendGuard sets setthink to call homing think function for homing missile test 02-02-2021
+ else
+ setthink(missile, W_Devastator_Think); //allows to activate the original devastator functions
+
+ if(missile.enemy != NULL)
+ missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
+ else
+ missile.projectiledeathtype = thiswep.m_id;
+
+
missile.cnt = time + WEP_CVAR(devastator, lifetime);
missile.rl_detonate_later = (fire & 2); // allow instant detonation
missile.flags = FL_PROJECTILE;
}
}
+
METHOD(Devastator, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
// aim and decide to fire if appropriate
P(class, prefix, guiderate, float, NONE) \
P(class, prefix, guidestop, float, NONE) \
P(class, prefix, health, float, NONE) \
+ P(class, prefix, homing_missile_active, bool, NONE) \
+ P(class, prefix, homing_missile_speed, float, NONE) \
+ P(class, prefix, homing_missile_speed_accel, float, NONE) \
+ P(class, prefix, homing_missile_speed_accel2, float, NONE) \
+ P(class, prefix, homing_missile_speed_decel, float, NONE) \
+ P(class, prefix, homing_missile_speed_max, float, NONE) \
+ P(class, prefix, homing_missile_speed_turnrate, float, NONE) \
P(class, prefix, lifetime, float, NONE) \
P(class, prefix, radius, float, NONE) \
P(class, prefix, refire, float, NONE) \