set g_balance_arc_beam_healing_hmax 150
set g_balance_arc_beam_healing_hps 50
set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 1
set g_balance_arc_overheat_max 5
set g_balance_arc_overheat_min 3
set g_balance_arc_beam_heat 1
set g_balance_arc_beam_refire 0.5
set g_balance_arc_beam_returnspeed 8
set g_balance_arc_beam_tightness 0.5
+set g_balance_arc_bolt 0
+set g_balance_arc_bolt_ammo 1
+set g_balance_arc_bolt_damage 25
+set g_balance_arc_bolt_damageforcescale 0
+set g_balance_arc_bolt_edgedamage 12.5
+set g_balance_arc_bolt_force 100
+set g_balance_arc_bolt_health 15
+set g_balance_arc_bolt_lifetime 5
+set g_balance_arc_bolt_radius 65
+set g_balance_arc_bolt_refire 0.16667
+set g_balance_arc_bolt_speed 2200
+set g_balance_arc_bolt_spread 0.03
set g_balance_arc_burst_ammo 15
set g_balance_arc_burst_damage 150
set g_balance_arc_burst_healing_aps 100
set g_balance_arc_beam_refire 0.5
set g_balance_arc_beam_returnspeed 8
set g_balance_arc_beam_tightness 0.5
+set g_balance_arc_bolt 0
+set g_balance_arc_bolt_ammo 1
+set g_balance_arc_bolt_damage 25
+set g_balance_arc_bolt_damageforcescale 0
+set g_balance_arc_bolt_edgedamage 12.5
+set g_balance_arc_bolt_force 100
+set g_balance_arc_bolt_health 15
+set g_balance_arc_bolt_lifetime 5
+set g_balance_arc_bolt_radius 65
+set g_balance_arc_bolt_refire 0.16667
+set g_balance_arc_bolt_speed 2200
+set g_balance_arc_bolt_spread 0.03
set g_balance_arc_burst_ammo 15
set g_balance_arc_burst_damage 250
set g_balance_arc_burst_healing_aps 100
set g_balance_arc_burst_healing_hps 100
set g_balance_arc_burst_heat 4
set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 1
set g_balance_arc_overheat_max 5
set g_balance_arc_overheat_min 3
set g_balance_arc_switchdelay_drop 0.3
set g_balance_arc_beam_refire 0.5
set g_balance_arc_beam_returnspeed 8
set g_balance_arc_beam_tightness 0.5
+set g_balance_arc_bolt 0
+set g_balance_arc_bolt_ammo 1
+set g_balance_arc_bolt_damage 25
+set g_balance_arc_bolt_damageforcescale 0
+set g_balance_arc_bolt_edgedamage 12.5
+set g_balance_arc_bolt_force 100
+set g_balance_arc_bolt_health 15
+set g_balance_arc_bolt_lifetime 5
+set g_balance_arc_bolt_radius 65
+set g_balance_arc_bolt_refire 0.16667
+set g_balance_arc_bolt_speed 2200
+set g_balance_arc_bolt_spread 0.03
set g_balance_arc_burst_ammo 0
set g_balance_arc_burst_damage 500
set g_balance_arc_burst_healing_aps 100
set g_balance_arc_burst_healing_hps 100
set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 1
set g_balance_arc_overheat_max 5
set g_balance_arc_overheat_min 3
set g_balance_arc_beam_heat 1
set g_balance_arc_beam_healing_hmax 150
set g_balance_arc_beam_healing_hps 50
set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 1
set g_balance_arc_overheat_max 5
set g_balance_arc_overheat_min 3
set g_balance_arc_beam_heat 1
set g_balance_arc_beam_refire 0.5
set g_balance_arc_beam_returnspeed 8
set g_balance_arc_beam_tightness 0.5
+set g_balance_arc_bolt 0
+set g_balance_arc_bolt_ammo 1
+set g_balance_arc_bolt_damage 25
+set g_balance_arc_bolt_damageforcescale 0
+set g_balance_arc_bolt_edgedamage 12.5
+set g_balance_arc_bolt_force 100
+set g_balance_arc_bolt_health 15
+set g_balance_arc_bolt_lifetime 5
+set g_balance_arc_bolt_radius 65
+set g_balance_arc_bolt_refire 0.16667
+set g_balance_arc_bolt_speed 2200
+set g_balance_arc_bolt_spread 0.03
set g_balance_arc_burst_ammo 15
set g_balance_arc_burst_damage 250
set g_balance_arc_burst_healing_aps 100
set g_balance_arc_beam_healing_hmax 150
set g_balance_arc_beam_healing_hps 50
set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 1
set g_balance_arc_overheat_max 5
set g_balance_arc_overheat_min 3
set g_balance_arc_beam_heat 1
set g_balance_arc_beam_refire 0.5
set g_balance_arc_beam_returnspeed 8
set g_balance_arc_beam_tightness 0.5
+set g_balance_arc_bolt 0
+set g_balance_arc_bolt_ammo 1
+set g_balance_arc_bolt_damage 25
+set g_balance_arc_bolt_damageforcescale 0
+set g_balance_arc_bolt_edgedamage 12.5
+set g_balance_arc_bolt_force 100
+set g_balance_arc_bolt_health 15
+set g_balance_arc_bolt_lifetime 5
+set g_balance_arc_bolt_radius 65
+set g_balance_arc_bolt_refire 0.16667
+set g_balance_arc_bolt_speed 2200
+set g_balance_arc_bolt_spread 0.03
set g_balance_arc_burst_ammo 15
set g_balance_arc_burst_damage 250
set g_balance_arc_burst_healing_aps 100
set g_balance_arc_beam_healing_hmax 150
set g_balance_arc_beam_healing_hps 50
set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 1
set g_balance_arc_overheat_max 5
set g_balance_arc_overheat_min 3
set g_balance_arc_beam_heat 1
set g_balance_arc_beam_refire 0.5
set g_balance_arc_beam_returnspeed 8
set g_balance_arc_beam_tightness 0.5
+set g_balance_arc_bolt 0
+set g_balance_arc_bolt_ammo 1
+set g_balance_arc_bolt_damage 25
+set g_balance_arc_bolt_damageforcescale 0
+set g_balance_arc_bolt_edgedamage 12.5
+set g_balance_arc_bolt_force 100
+set g_balance_arc_bolt_health 15
+set g_balance_arc_bolt_lifetime 5
+set g_balance_arc_bolt_radius 65
+set g_balance_arc_bolt_refire 0.16667
+set g_balance_arc_bolt_speed 2200
+set g_balance_arc_bolt_spread 0.03
set g_balance_arc_burst_ammo 15
set g_balance_arc_burst_damage 250
set g_balance_arc_burst_healing_aps 100
trailspacing 12
velocityjitter 50 50 50
velocityoffset 0 0 15
+effect arc_muzzleflash
+ type smoke
+ alpha 256 256 512
+ color 0x00ff00 0x8f4333
+ count 2
+ lightcolor 0.3 2 0.2
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ size 5 5
+ tex 0 8
+ velocityjitter 6 6 6
+ velocitymultiplier 0.010000
+effect arc_muzzleflash
+ type spark
+ airfriction 12
+ alpha 0 128 1024
+ color 0x00ff00 0x8f4333
+ count 15
+ originjitter 1 1 1
+ rotate -180 180 -400 400
+ size 5 10
+ stretchfactor 2
+ tex 48 55
+ velocityjitter 200 200 200
+ velocitymultiplier 0.500000
+effect arc_bolt_explode
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 8 4 1
+ lightradiusfade 400
+ lightradius 120
+ originjitter 14 14 14
+ size 28 38
+ tex 8 16
+effect arc_bolt_explode
+ type smoke
+ airfriction 8
+ alpha 80 200 356
+ bounce 1.500000
+ color 0x00ffff 0x00ffff
+ count 3.500000
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 5
+ size 16 26
+ tex 48 55
+ velocityjitter 156 156 156
+effect arc_bolt_explode
+ type static
+ airfriction 12
+ alpha 128 256 456
+ bounce 1.500000
+ color 0x00ff00 0x8f4333
+ count 12
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 15
+ size 20 26
+ tex 48 55
+ velocityjitter 286 286 286
+effect arc_bolt_explode
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 16
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 96 96 96
+effect arc_bolt_explode
+ type spark
+ airfriction 1
+ alpha 644 956 684
+ bounce 1.600000
+ color 0x00ff00 0x8f4333
+ count 16
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 16 16 16
+ size 1 0.100000
+ tex 40 40
+ velocityjitter 224 224 224
+ velocityoffset 0 0 80
--- /dev/null
+Plane01,arc_projectile_core
+Plane02,arc_projectile_long
set g_nades_bonus_onstrength 1 "Always give bonus grenades to players that have the strength powerup"
set g_nades_bonus_max 3 "Maximum number of bonus grenades"
set g_nades_bonus_only 0 "Disallow regular nades, only bonus nades can be used"
+set g_nades_nade_small 0 "Use smaller nade size, makes shooting them harder, legacy setting"
// Bonus score
set g_nades_bonus_score_max 120 "Score value that will give a bonus nade"
set g_nades_bonus_score_minor 5 "Score given for minor actions (pickups, regular frags etc.)"
drawfill(panel_pos - '1 1 0' * panel_bg_border, panel_size + '2 2 0' * panel_bg_border, '1 1 1', .1, DRAWFLAG_NORMAL);
}
// draw cursor after performing move/resize to have the panel pos/size updated before mouse_over_panel
- const vector cursorsize = '32 32 0';
float cursor_alpha = 1 - autocvar__menu_alpha;
if(!mouse_over_panel)
- drawpic(mousepos, strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), cursorsize, '1 1 1', cursor_alpha, DRAWFLAG_NORMAL);
+ draw_cursor_normal(mousepos, '1 1 1', cursor_alpha);
else if(mouse_over_panel == 1)
- drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", autocvar_menu_skin, "/cursor_move.tga"), cursorsize, '1 1 1', cursor_alpha, DRAWFLAG_NORMAL);
+ draw_cursor(mousepos, '0.5 0.5 0', "/cursor_move", '1 1 1', cursor_alpha);
else if(mouse_over_panel == 2)
- drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", autocvar_menu_skin, "/cursor_resize.tga"), cursorsize, '1 1 1', cursor_alpha, DRAWFLAG_NORMAL);
+ draw_cursor(mousepos, '0.5 0.5 0', "/cursor_resize", '1 1 1', cursor_alpha);
else
- drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", autocvar_menu_skin, "/cursor_resize2.tga"), cursorsize, '1 1 1', cursor_alpha, DRAWFLAG_NORMAL);
+ draw_cursor(mousepos, '0.5 0.5 0', "/cursor_resize2", '1 1 1', cursor_alpha);
prevMouseClicked = mouseClicked;
}
}
- const vector cursor_size = '32 32 0';
- drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), cursor_size, '1 1 1', 0.8, DRAWFLAG_NORMAL);
+ draw_cursor_normal(mousepos, '1 1 1', 0.8);
}
void HUD_Radar()
FOREACH_ENTITY_FLAGS(teamradar_icon, 0xFFFFFF, LAMBDA(
if ( hud_panel_radar_mouse )
if ( it.health > 0 )
- if ( it.team == myteam+1 )
+ if ( it.team == myteam+1 || gametype == MAPINFO_TYPE_RACE )
{
vector coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(it.origin));
if(vdist((mousepos - coord), <, 8))
#define DP_CSQC_ENTITY_REMOVE_IS_B0RKED
+void draw_cursor(vector pos, vector ofs, string img, vector col, float a)
+{
+ ofs = eX * (ofs.x * SIZE_CURSOR.x) + eY * (ofs.y * SIZE_CURSOR.y);
+ drawpic(pos - ofs, strcat(draw_currentSkin, img), SIZE_CURSOR, col, a, DRAWFLAG_NORMAL);
+}
+
+void draw_cursor_normal(vector pos, vector col, float a)
+{
+ draw_cursor(pos, OFFSET_CURSOR, "/cursor", col, a);
+}
+
+void LoadMenuSkinValues()
+{
+ int fh = -1;
+ if(cvar_string("menu_skin") != "")
+ {
+ draw_currentSkin = strcat("gfx/menu/", cvar_string("menu_skin"));
+ fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ);
+ }
+ if(fh < 0 && cvar_defstring("menu_skin") != "")
+ {
+ cvar_set("menu_skin", cvar_defstring("menu_skin"));
+ draw_currentSkin = strcat("gfx/menu/", cvar_string("menu_skin"));
+ fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ);
+ }
+ if(fh < 0)
+ {
+ draw_currentSkin = "gfx/menu/default";
+ fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ);
+ }
+
+ draw_currentSkin = strzone(draw_currentSkin);
+
+ if(fh >= 0)
+ {
+ string s;
+ while((s = fgets(fh)))
+ {
+ int n = tokenize_console(s);
+ if (n < 2)
+ continue;
+ if(substring(argv(0), 0, 2) == "//")
+ continue;
+ if(argv(0) == "SIZE_CURSOR")
+ SIZE_CURSOR = stov(substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)));
+ else if(argv(0) == "OFFSET_CURSOR")
+ OFFSET_CURSOR = stov(substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)));
+ }
+ fclose(fh);
+ }
+}
+
// CSQC_Init : Called every time the CSQC code is initialized (essentially at map load)
// Useful for precaching things
}
hud_skin_path = strzone(strcat("gfx/hud/", autocvar_hud_skin));
- draw_currentSkin = strzone(strcat("gfx/menu/", cvar_string("menu_skin")));
+ LoadMenuSkinValues();
}
// CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
float FONT_USER = 8;
+
+vector OFFSET_CURSOR = '0 0 0';
+vector SIZE_CURSOR = '32 32 0';
+void draw_cursor(vector pos, vector ofs, string img, vector col, float a);
+void draw_cursor_normal(vector pos, vector col, float a);
+void LoadMenuSkinValues();
+
// --------------------------------------------------------------------------
// Scoreboard stuff
MapVote_DrawAbstain(pos, dist.x, xmax - xmin, tmp, i);
}
- drawpic(mv_mousepos, strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), '32 32 0', '1 1 1', 1 - autocvar__menu_alpha, DRAWFLAG_NORMAL);
+ draw_cursor_normal(mv_mousepos, '1 1 1', 1 - autocvar__menu_alpha);
}
void Cmd_MapVote_MapDownload(float argc)
}
}
- vector cursorsize = '32 32 0';
- drawpic(mousepos, strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), cursorsize, '1 1 1', 0.8, DRAWFLAG_NORMAL);
+ draw_cursor_normal(mousepos, '1 1 1', 0.8);
prevMouseClicked = mouseClicked;
}
HANDLE(GRENADE_BOUNCING) this.traileffect = EFFECT_TR_GRENADE.m_id; break;
HANDLE(MINE) this.traileffect = EFFECT_TR_GRENADE.m_id; break;
HANDLE(BLASTER) this.traileffect = EFFECT_Null.m_id; break;
+ HANDLE(ARC_BOLT) this.traileffect = EFFECT_Null.m_id; break;
HANDLE(HLAC) this.traileffect = EFFECT_Null.m_id; break;
HANDLE(PORTO_RED) this.traileffect = EFFECT_TR_WIZSPIKE.m_id; this.scale = 4; break;
HANDLE(PORTO_BLUE) this.traileffect = EFFECT_TR_WIZSPIKE.m_id; this.scale = 4; break;
const int PROJECTILE_ROCKETMINSTA_LASER = 34;
+const int PROJECTILE_ARC_BOLT = 35;
+
// projectile IDs 40-50 reserved
const int PROJECTILE_RPC = 60;
EFFECT(0, SMOKE_LARGE, "smoke_large")
+EFFECT(0, ARC_MUZZLEFLASH, "arc_muzzleflash")
EFFECT(0, BLASTER_IMPACT, "laser_impact")
EFFECT(0, BLASTER_MUZZLEFLASH, "laser_muzzleflash")
EFFECT(0, ARC_BEAM_HEAL, "arc_beam_heal")
EFFECT(0, ARC_BEAM_HEAL_IMPACT, "arc_beam_healimpact")
EFFECT(0, ARC_BEAM_HEAL_IMPACT2, "healray_impact")
+EFFECT(0, ARC_BOLT_EXPLODE, "arc_bolt_explode")
EFFECT(0, ARC_OVERHEAT, "arc_overheat")
EFFECT(0, ARC_OVERHEAT_FIRE, "arc_overheat_fire")
EFFECT(0, ARC_SMOKE, "arc_smoke")
#include "effectinfo_buffs.inc"
#include "effectinfo_instagib.inc"
+
+DEF(arc_muzzleflash);
+SUB(arc_muzzleflash) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x8f4333";
+ MY(count) = 2;
+ MY(lightcolor) = '0.3 2.0 0.2';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+SUB(arc_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x8f4333";
+ MY(count) = 15;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -400;
+ MY(spin_max) = 400;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(arc_bolt_explode);
+// decal
+SUB(arc_bolt_explode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '8.0 4.0 1.0';
+ MY(lightradiusfade) = 400;
+ MY(lightradius) = 120;
+ MY(originjitter) = '14.0 14.0 14.0';
+ MY(size_min) = 28;
+ MY(size_max) = 38;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// fire effect which make bright dot inside
+SUB(arc_bolt_explode) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 80;
+ MY(alpha_max) = 200;
+ MY(alpha_fade) = 356;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x00ffff";
+ MY(color_max) = "0x00ffff";
+ MY(count) = 3.500000;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 5;
+ MY(size_min) = 16;
+ MY(size_max) = 26;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '156.0 156.0 156.0';
+}
+// fire effect which expands then slows
+SUB(arc_bolt_explode) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 456;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x8f4333";
+ MY(count) = 12;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 15;
+ MY(size_min) = 20;
+ MY(size_max) = 26;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '286.0 286.0 286.0';
+}
+// underwater bubbles
+SUB(arc_bolt_explode) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 16;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// bouncing sparks
+SUB(arc_bolt_explode) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 684;
+ MY(bounce) = 1.600000;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x8f4333";
+ MY(count) = 16;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 1;
+ MY(size_max) = 0.100000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '224.0 224.0 224.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
{ vector v = '0 0 0'; v.y = ReadByte() / 256 * 360; this.angles = v; }) \
\
PROP(false, health, \
- { WriteByte(chan, this.health / 10); /* FIXME: use a better scale? */ }, \
+ { WriteByte(chan, bound(0, this.health / 10, 255)); /* FIXME: use a better scale? */ }, \
{ this.healthvalue = ReadByte() * 10; }) \
\
PROP(false, armorvalue, \
- { WriteByte(chan, this.armorvalue / 10); /* FIXME: use a better scale? */ }, \
+ { WriteByte(chan, bound(0, this.armorvalue / 10, 255)); /* FIXME: use a better scale? */ }, \
{ this.armorvalue = ReadByte() * 10; }) \
\
PROP(true, netname, \
#ifdef SVQC
#include <common/t_items.qh>
- #include <server/constants.qh>
#endif
#include "ammo.qh"
MODEL(JetpackRegen_ITEM, Item_Model("g_fuelregen.md3"));
#endif
-REGISTER_ITEM(JetpackRegen, Pickup) {
+REGISTER_ITEM(JetpackRegen, Powerup) {
#ifndef MENUQC
this.m_model = MDL_JetpackRegen_ITEM;
#endif
this.m_waypointblink = 2;
#ifdef SVQC
this.m_botvalue = BOT_PICKUP_RATING_LOW;
- this.m_itemflags = FL_POWERUP;
this.m_itemid = IT_FUEL_REGEN;
this.m_pickupevalfunc = commodity_pickupevalfunc;
- this.m_respawntime = GET(g_pickup_respawntime_powerup);
- this.m_respawntimejitter = GET(g_pickup_respawntimejitter_powerup);
#endif
}
if ( HUD_MinigameMenu_IsOpened() && HUD_mouse_over(HUD_PANEL(MINIGAME_MENU)) )
HUD_MinigameMenu_MouseInput();
- vector cursorsize = '32 32 0';
- drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"),
- cursorsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ draw_cursor_normal(mousepos-'8 4 0', '1 1 1', panel_fg_alpha);
}
bool HUD_Minigame_Showpanels()
MODEL(PROJECTILE_HAGAR, "models/hagarmissile.mdl");
MODEL(PROJECTILE_HAGAR_BOUNCING, "models/hagarmissile.mdl");
+MODEL(PROJECTILE_ARC_BOLT, "models/arctrail.mdl");
+
// napalm grenade
MODEL(PROJECTILE_NAPALM_FOUNTAIN, "null");
// fireball primary
// this... is ridiculous (TODO: fix!)
if(frag_attacker.buffs & BUFF_VAMPIRE.m_itemid)
if(!frag_target.vehicle)
- if(DEATH_WEAPONOF(frag_deathtype) != WEP_ARC)
if(!ITEM_DAMAGE_NEEDKILL(frag_deathtype))
if(!IS_DEAD(frag_target))
if(IS_PLAYER(frag_target) || IS_MONSTER(frag_target))
return (false
|| it.instanceOfPowerup
|| Item_ItemsTime_SpectatorOnly(it)
- || it == ITEM_JetpackRegen
);
}
#ifdef IMPLEMENTATION
+#ifdef SVQC
+bool autocvar_g_nades_nade_small;
+#endif
+
+REGISTER_STAT(NADES_SMALL, int, autocvar_g_nades_nade_small)
+
#ifndef MENUQC
entity Nade_TrailEffect(int proj, int nade_team)
{
entity nade_type = Nade_FromProjectile(self.cnt);
if (nade_type == NADE_TYPE_Null) return;
- self.mins = '-16 -16 -16';
- self.maxs = '16 16 16';
+ if(STAT(NADES_SMALL, NULL))
+ {
+ self.mins = '-8 -8 -8';
+ self.maxs = '8 8 8';
+ }
+ else
+ {
+ self.mins = '-16 -16 -16';
+ self.maxs = '16 16 16';
+ }
self.colormod = nade_type.m_color;
self.move_movetype = MOVETYPE_BOUNCE;
self.move_touch = func_null;
//setmodel(_nade, MDL_PROJECTILE_NADE);
//setattachment(_nade, world, "");
PROJECTILE_MAKETRIGGER(_nade);
- setsize(_nade, '-16 -16 -16', '16 16 16');
+ if(STAT(NADES_SMALL, e))
+ setsize(_nade, '-8 -8 -8', '8 8 8');
+ else
+ setsize(_nade, '-16 -16 -16', '16 16 16');
_nade.movetype = MOVETYPE_BOUNCE;
tracebox(_nade.origin, _nade.mins, _nade.maxs, _nade.origin, false, _nade);
MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Accordeon%s%s"), "")
MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Accordeon%s%s"), "")
MSG_INFO_NOTIF(1, INFO_WEAPON_ARC_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponarc", _("^BG%s%s^K1 was electrocuted by ^BG%s^K1's Arc%s%s"), "")
+ MSG_INFO_NOTIF(1, INFO_WEAPON_ARC_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponarc", _("^BG%s%s^K1 was blasted by ^BG%s^K1's Arc bolts%s%s"), "")
MSG_INFO_NOTIF(1, INFO_WEAPON_BLASTER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponlaser", _("^BG%s%s^K1 was shot to death by ^BG%s^K1's Blaster%s%s"), "")
MSG_INFO_NOTIF(1, INFO_WEAPON_BLASTER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponlaser", _("^BG%s^K1 shot themself to hell with their Blaster%s%s"), "")
MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponcrylink", _("^BG%s%s^K1 felt the strong pull of ^BG%s^K1's Crylink%s%s"), "")
MSG_MULTI_NOTIF(1, WEAPON_ACCORDEON_MURDER, NO_MSG, INFO_WEAPON_ACCORDEON_MURDER, NO_MSG)
MSG_MULTI_NOTIF(1, WEAPON_ACCORDEON_SUICIDE, NO_MSG, INFO_WEAPON_ACCORDEON_SUICIDE, CENTER_DEATH_SELF_GENERIC)
MSG_MULTI_NOTIF(1, WEAPON_ARC_MURDER, NO_MSG, INFO_WEAPON_ARC_MURDER, NO_MSG)
+ MSG_MULTI_NOTIF(1, WEAPON_ARC_MURDER_SPRAY, NO_MSG, INFO_WEAPON_ARC_MURDER_SPRAY, NO_MSG)
MSG_MULTI_NOTIF(1, WEAPON_BLASTER_MURDER, NO_MSG, INFO_WEAPON_BLASTER_MURDER, NO_MSG)
MSG_MULTI_NOTIF(1, WEAPON_BLASTER_SUICIDE, NO_MSG, INFO_WEAPON_BLASTER_SUICIDE, CENTER_DEATH_SELF_GENERIC)
MSG_MULTI_NOTIF(1, WEAPON_CRYLINK_MURDER, NO_MSG, INFO_WEAPON_CRYLINK_MURDER, NO_MSG)
#ifdef SVQC
PHYS_TELEPORT_TIME(this) = time + 2; // safety net
#elif defined(CSQC)
- pmove_waterjumptime = time + 2;
+ pmove_waterjumptime = 2;
#endif
}
}
PM_Footsteps(this);
}
+#ifdef SVQC
if(IsFlying(this))
this.wasFlying = 1;
+#endif
if (IS_PLAYER(this))
CheckPlayerJump(this);
{
this.velocity_x = this.movedir.x;
this.velocity_y = this.movedir.y;
- if (time > PHYS_TELEPORT_TIME(this) || this.waterlevel == WATERLEVEL_NONE)
+ if (time > PHYS_TELEPORT_TIME(this) || this.waterlevel == WATERLEVEL_NONE
+ #ifdef CSQC
+ || pmove_waterjumptime <= 0
+ #endif
+ )
{
this.flags &= ~FL_WATERJUMP;
PHYS_TELEPORT_TIME(this) = 0;
+ #ifdef CSQC
+ pmove_waterjumptime = 0;
+ #endif
}
}
#define X(BEGIN, P, END, class, prefix) \
BEGIN(class) \
+ P(class, prefix, bolt, float, NONE) \
+ P(class, prefix, bolt_ammo, float, NONE) \
+ P(class, prefix, bolt_damageforcescale, float, NONE) \
+ P(class, prefix, bolt_damage, float, NONE) \
+ P(class, prefix, bolt_edgedamage, float, NONE) \
+ P(class, prefix, bolt_force, float, NONE) \
+ P(class, prefix, bolt_health, float, NONE) \
+ P(class, prefix, bolt_lifetime, float, NONE) \
+ P(class, prefix, bolt_radius, float, NONE) \
+ P(class, prefix, bolt_refire, float, NONE) \
+ P(class, prefix, bolt_speed, float, NONE) \
+ P(class, prefix, bolt_spread, float, NONE) \
P(class, prefix, beam_ammo, float, NONE) \
P(class, prefix, beam_animtime, float, NONE) \
P(class, prefix, beam_botaimlifetime, float, NONE) \
P(class, prefix, burst_healing_hps, float, NONE) \
P(class, prefix, burst_heat, float, NONE) /* heat increase per second (secondary) */ \
P(class, prefix, cooldown, float, NONE) /* heat decrease per second when resting */ \
+ P(class, prefix, cooldown_release, float, NONE) /* delay weapon re-use when releasing button */ \
P(class, prefix, overheat_max, float, NONE) /* maximum heat before jamming */ \
P(class, prefix, overheat_min, float, NONE) /* minimum heat to wait for cooldown */ \
P(class, prefix, switchdelay_drop, float, NONE) \
WriteByte(MSG_ENTITY, WEP_CVAR(arc, beam_tightness) * 10);
WriteByte(MSG_ENTITY, drawlocal);
+ WriteByte(MSG_ENTITY, etof(this.owner));
}
if(sf & ARC_SF_START) // starting location
{
//dprint("Heat: ",ftos(player.arc_heat_percent*100),"%\n");
}
+void W_Arc_Bolt_Explode()
+{SELFPARAM();
+ self.event_damage = func_null;
+ RadiusDamage(self, self.realowner, WEP_CVAR(arc, bolt_damage), WEP_CVAR(arc, bolt_edgedamage), WEP_CVAR(arc, bolt_radius), world, world, WEP_CVAR(arc, bolt_force), self.projectiledeathtype, other);
+
+ remove(self);
+}
+
+void W_Arc_Bolt_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+ if(this.health <= 0)
+ return;
+
+ if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1))
+ return; // g_projectiles_damage says to halt
+
+ this.health = this.health - damage;
+ this.angles = vectoangles(this.velocity);
+
+ if(this.health <= 0)
+ WITH(entity, self, this, W_PrepareExplosionByDamage(attacker, this.think));
+}
+
+void W_Arc_Bolt_Touch()
+{SELFPARAM();
+ PROJECTILE_TOUCH;
+ self.use();
+}
+
+void W_Arc_Attack_Bolt(Weapon thiswep)
+{SELFPARAM();
+ entity missile;
+
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR(arc, bolt_ammo));
+
+ W_SetupShot(self, false, 2, SND(LASERGUN_FIRE), CH_WEAPON_A, WEP_CVAR(arc, bolt_damage));
+
+ Send_Effect(EFFECT_ARC_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
+
+ missile = new(missile);
+ missile.owner = missile.realowner = self;
+ missile.bot_dodge = true;
+ missile.bot_dodgerating = WEP_CVAR(arc, bolt_damage);
+
+ missile.takedamage = DAMAGE_YES;
+ missile.health = WEP_CVAR(arc, bolt_health);
+ missile.damageforcescale = WEP_CVAR(arc, bolt_damageforcescale);
+ missile.event_damage = W_Arc_Bolt_Damage;
+ missile.damagedbycontents = true;
+
+ missile.touch = W_Arc_Bolt_Touch;
+ missile.use = W_Arc_Bolt_Explode;
+ missile.think = adaptor_think2use_hittype_splash;
+ missile.nextthink = time + WEP_CVAR(arc, bolt_lifetime);
+ PROJECTILE_MAKETRIGGER(missile);
+ missile.projectiledeathtype = WEP_ARC.m_id | HITTYPE_SECONDARY;
+ setorigin(missile, w_shotorg);
+ setsize(missile, '0 0 0', '0 0 0');
+
+ missile.movetype = MOVETYPE_FLY;
+ W_SetupProjVelocity_PRE(missile, arc, bolt_);
+
+ missile.angles = vectoangles(missile.velocity);
+ missile.flags = FL_PROJECTILE;
+ missile.missile_flags = MIF_SPLASH;
+
+ CSQCProjectile(missile, true, PROJECTILE_ARC_BOLT, true);
+
+ MUTATOR_CALLHOOK(EditProjectile, self, missile);
+}
+
void W_Arc_Beam_Think()
{SELFPARAM();
if(self != self.owner.arc_beam)
float burst = 0;
- if( self.owner.BUTTON_ATCK2 || self.beam_bursting)
+ if( (self.owner.BUTTON_ATCK2 && !WEP_CVAR(arc, bolt)) || self.beam_bursting)
{
if(!self.beam_bursting)
self.beam_bursting = true;
||
IS_DEAD(self.owner)
||
+ gameover
+ ||
(!self.owner.BUTTON_ATCK && !burst )
||
STAT(FROZEN, self.owner)
if ( cooldown_speed )
{
- self.owner.arc_overheat = time + self.beam_heat / cooldown_speed;
+ if ( WEP_CVAR(arc, cooldown_release) || (WEP_CVAR(arc, overheat_max) > 0 && self.beam_heat >= WEP_CVAR(arc, overheat_max)) )
+ self.owner.arc_overheat = time + self.beam_heat / cooldown_speed;
self.owner.arc_cooldown = cooldown_speed;
}
Arc_Player_SetHeat(actor);
Arc_Smoke();
+ bool beam_fire2 = ((fire & 2) && !WEP_CVAR(arc, bolt));
+
if (time >= actor.arc_overheat)
- if ((fire & 1) || (fire & 2) || actor.arc_beam.beam_bursting)
+ if ((fire & 1) || beam_fire2 || actor.arc_beam.beam_bursting)
{
if(actor.arc_BUTTON_ATCK_prev)
if((!actor.arc_beam) || wasfreed(actor.arc_beam))
{
- if(weapon_prepareattack(thiswep, actor, weaponentity, boolean(fire & 2), 0))
+ if(weapon_prepareattack(thiswep, actor, weaponentity, boolean(beam_fire2), 0))
{
- W_Arc_Beam(boolean(fire & 2));
+ W_Arc_Beam(boolean(beam_fire2));
if(!actor.arc_BUTTON_ATCK_prev)
{
return;
}
+ else if(fire & 2)
+ {
+ if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(arc, bolt_refire)))
+ {
+ W_Arc_Attack_Bolt(thiswep);
+ weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, bolt_refire), w_ready);
+ }
+ }
if(actor.arc_BUTTON_ATCK_prev)
{
METHOD(Arc, wr_checkammo2, bool(entity thiswep))
{
SELFPARAM();
- return WEP_CVAR(arc, overheat_max) > 0 &&
- ((!WEP_CVAR(arc, burst_ammo)) || (self.(thiswep.ammo_field) > 0));
+ if(WEP_CVAR(arc, bolt))
+ {
+ float ammo_amount = self.(thiswep.ammo_field) >= WEP_CVAR(arc, bolt_ammo);
+ ammo_amount += self.(weapon_load[WEP_ARC.m_id]) >= WEP_CVAR(arc, bolt_ammo);
+ return ammo_amount;
+ }
+ else
+ return WEP_CVAR(arc, overheat_max) > 0 &&
+ ((!WEP_CVAR(arc, burst_ammo)) || (self.(thiswep.ammo_field) > 0));
}
METHOD(Arc, wr_killmessage, int(entity thiswep))
{
- return WEAPON_ARC_MURDER;
+ if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_ARC_MURDER_SPRAY;
+ else
+ return WEAPON_ARC_MURDER;
}
METHOD(Arc, wr_drop, void(entity thiswep))
{
}
#endif
#ifdef CSQC
+bool autocvar_cl_arcbeam_teamcolor = true;
+
+ METHOD(Arc, wr_impacteffect, void(entity thiswep))
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ {
+ vector org2;
+ org2 = w_org + w_backoff * 6;
+ pointparticles(EFFECT_ARC_BOLT_EXPLODE, org2, w_backoff * 1000, 1);
+ if(!w_issilent) { sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }
+ }
+ }
+
void Draw_ArcBeam_callback(vector start, vector hit, vector end)
{
entity beam = Draw_ArcBeam_callback_entity;
{
self.beam_usevieworigin = 0;
}
+
+ self.sv_entnum = ReadByte();
}
if(!self.beam_usevieworigin)
if(sf & ARC_SF_BEAMTYPE) // beam type
{
self.beam_type = ReadByte();
+
+ vector beamcolor = ((autocvar_cl_arcbeam_teamcolor) ? colormapPaletteColor(stof(getplayerkeyvalue(self.sv_entnum - 1, "colors")) & 0x0F, true) : '1 1 1');
switch(self.beam_type)
{
case ARC_BT_MISS:
{
- self.beam_color = '1 1 1';
+ self.beam_color = beamcolor;
self.beam_alpha = 0.5;
self.beam_thickness = 8;
self.beam_traileffect = (EFFECT_ARC_BEAM);
}
case ARC_BT_WALL: // grenadelauncher_muzzleflash healray_muzzleflash
{
- self.beam_color = '1 1 1';
+ self.beam_color = beamcolor;
self.beam_alpha = 0.5;
self.beam_thickness = 8;
self.beam_traileffect = (EFFECT_ARC_BEAM);
}
case ARC_BT_HEAL:
{
- self.beam_color = '1 1 1';
+ self.beam_color = beamcolor;
self.beam_alpha = 0.5;
self.beam_thickness = 8;
self.beam_traileffect = (EFFECT_ARC_BEAM_HEAL);
}
case ARC_BT_HIT:
{
- self.beam_color = '1 1 1';
+ self.beam_color = beamcolor;
self.beam_alpha = 0.5;
self.beam_thickness = 8;
self.beam_traileffect = (EFFECT_ARC_BEAM);
}
case ARC_BT_BURST_MISS:
{
- self.beam_color = '1 1 1';
+ self.beam_color = beamcolor;
self.beam_alpha = 0.5;
self.beam_thickness = 14;
self.beam_traileffect = (EFFECT_ARC_BEAM);
}
case ARC_BT_BURST_WALL:
{
- self.beam_color = '1 1 1';
+ self.beam_color = beamcolor;
self.beam_alpha = 0.5;
self.beam_thickness = 14;
self.beam_traileffect = (EFFECT_ARC_BEAM);
}
case ARC_BT_BURST_HEAL:
{
- self.beam_color = '1 1 1';
+ self.beam_color = beamcolor;
self.beam_alpha = 0.5;
self.beam_thickness = 14;
self.beam_traileffect = (EFFECT_ARC_BEAM_HEAL);
}
case ARC_BT_BURST_HIT:
{
- self.beam_color = '1 1 1';
+ self.beam_color = beamcolor;
self.beam_alpha = 0.5;
self.beam_thickness = 14;
self.beam_traileffect = (EFFECT_ARC_BEAM);
#include "linkedlist.qh"
#include "log.qh"
#include "map.qh"
+#include "markdown.qh"
#include "math.qh"
#include "misc.qh"
#include "net.qh"
--- /dev/null
+#include "test.qh"
+
+/**
+ * handle string spacing as markdown:
+ * - two spaces escape a linebreak (otherwise text wraps)
+ * - two linebreaks become a paragraph (remain unchanged)
+ */
+string markdown(string s)
+{
+ string buf = "";
+ int lines = 0;
+ int spaces = 0;
+ FOREACH_CHAR(s, true, {
+ switch (it) {
+ default:
+ for (; spaces > 0; --spaces) {
+ buf = strcat(buf, " ");
+ }
+ buf = strcat(buf, chr2str(it));
+ break;
+ case ' ':
+ spaces += 1;
+ break;
+ case '\n':
+ lines += 1;
+ if (lines > 1) {
+ lines = 0;
+ spaces = 0;
+ buf = strcat(buf, "\n\n");
+ break;
+ }
+ if (spaces < 2) {
+ spaces = 1;
+ } else {
+ spaces = 0;
+ buf = strcat(buf, "\n");
+ }
+ break;
+ }
+ });
+ return buf;
+}
+
+TEST(Markdown, LineWrap)
+{
+ #define X(expect, in) MACRO_BEGIN \
+ string out = markdown(in); \
+ EXPECT_TRUE(expect == out); \
+ LOG_INFO(expect); \
+ LOG_INFO(out); \
+ MACRO_END
+
+ // identity
+ X("lorem ipsum", "lorem ipsum");
+ // trim trailing space
+ X("lorem ipsum", "lorem ipsum ");
+ // allow manual input wrapping
+ X("lorem ipsum", "lorem\nipsum");
+ // line break
+ X("lorem\nipsum", "lorem \nipsum");
+ // paragraph
+ X("lorem\n\nipsum", "lorem\n\nipsum");
+ SUCCEED();
+ #undef X
+}
entity deathent = Deathtypes_from(deathtype - DT_FIRST);
if (!deathent) { backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n"); return; }
+ if(g_cts && deathtype == DEATH_KILL.m_id)
+ return; // TODO: somehow put this in CTS gamemode file!
+
if(murder)
{
if(deathent.death_msgmurder)
// online ban list
OnlineBanList_URI_Get_Callback(id, status, data);
}
+ else if (MUTATOR_CALLHOOK(URI_GetCallback, id, status, data))
+ {
+ // handled by a mutator
+ }
else
{
LOG_INFO("Received HTTP request data for an invalid id ", ftos(id), ".\n");
float pct_curteam;
float pct_newteam;
MUTATOR_HOOKABLE(Player_ChangeTeam, EV_Player_ChangeTeam);
+
+/**/
+#define EV_URI_GetCallback(i, o) \
+ /**/ i(float, uricb_id) \
+ /**/ i(float, uricb_status) \
+ /**/ i(string, uricb_data) \
+ /**/
+float uricb_id;
+float uricb_status;
+string uricb_data;
+MUTATOR_HOOKABLE(URI_GetCallback, EV_URI_GetCallback);
#endif
+arc_projectile_core
+{
+ surfaceparm nonsolid
+ surfaceparm nolightmap
+ deformVertexes autosprite
+ {
+ map textures/projectiles/arc_projectile_core.tga
+ blendfunc GL_SRC_ALPHA GL_ONE
+ rgbGen lightingDiffuse
+ }
+}
+arc_projectile_long
+{
+ surfaceparm nonsolid
+ surfaceparm nolightmap
+ deformVertexes autosprite2
+ {
+ map textures/projectiles/arc_projectile_long.tga
+ blendfunc GL_SRC_ALPHA GL_ONE
+ rgbGen lightingDiffuse
+ }
+}
crylink_projectile_core
{
surfaceparm nonsolid