]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'terencehill/weaponmodel_effects_improvements' into 'master'
authorMario <zacjardine@y7mail.com>
Sat, 13 Feb 2016 23:28:34 +0000 (23:28 +0000)
committerMario <zacjardine@y7mail.com>
Sat, 13 Feb 2016 23:28:34 +0000 (23:28 +0000)
weaponmodel effects improvements 2

cl_followmodel and cl_leanmodel:
* fps independent
* less settings (cvars)
* fixed glitch passing through warpzones / teleports

cl_followmodel:
* more realistic (depends on pitch too)

See merge request !279

40 files changed:
bal-wep-nexuiz25.cfg
bal-wep-overkill.cfg
bal-wep-samual.cfg
bal-wep-xdf.cfg
bal-wep-xonotic.cfg
bal-wep-xpm.cfg
effectinfo.txt
models/arctrail.mdl [new file with mode: 0644]
models/arctrail.mdl_0.skin [new file with mode: 0644]
mutators.cfg
qcsrc/client/hud/hud_config.qc
qcsrc/client/hud/panel/radar.qc
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/mapvoting.qc
qcsrc/client/quickmenu.qc
qcsrc/client/weapons/projectile.qc
qcsrc/common/constants.qh
qcsrc/common/effects/all.inc
qcsrc/common/effects/effectinfo.inc
qcsrc/common/ent_cs.qc
qcsrc/common/items/item/jetpack.qc
qcsrc/common/minigames/cl_minigames_hud.qc
qcsrc/common/models/all.inc
qcsrc/common/mutators/mutator/buffs/buffs.qc
qcsrc/common/mutators/mutator/itemstime.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/notifications.inc
qcsrc/common/physics/player.qc
qcsrc/common/weapons/weapon/arc.qc
qcsrc/lib/_all.inc
qcsrc/lib/markdown.qh [new file with mode: 0644]
qcsrc/server/g_damage.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/events.qh
scripts/projectiles.shader
textures/projectiles/arc_projectile_core.tga [new file with mode: 0644]
textures/projectiles/arc_projectile_core_glow.tga [new file with mode: 0644]
textures/projectiles/arc_projectile_long.tga [new file with mode: 0644]
textures/projectiles/arc_projectile_long_glow.tga [new file with mode: 0644]

index 4800657f73e0ab64d250912f39fd2ba922e420ae..bb7ab5f6780738b28e140ba39d829e2725e84206 100644 (file)
@@ -741,6 +741,7 @@ set g_balance_arc_beam_healing_aps 50
 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
@@ -751,6 +752,18 @@ set g_balance_arc_beam_range 1000
 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
index 8f8e24ca7d0fee0ecff597ac65efa4fb5f3b8126..626ada04eab958e36e003f4ec0f0b8fbe04f2ff9 100644 (file)
@@ -746,12 +746,25 @@ set g_balance_arc_beam_range 1000
 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
index 9fde147a6ed24ff7534642ee1d5fda84fcce4c29..5545c6502cf6bdd38e11c80c7ea0cc852b87241c 100644 (file)
@@ -264,11 +264,24 @@ set g_balance_arc_beam_range 1000
 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
index ce00717c4e3e717fe59199bd17e31f0e235e8b61..cf7a05f6b5b0787fc13555bdc7ce2b8b601d1acf 100644 (file)
@@ -741,6 +741,7 @@ set g_balance_arc_beam_healing_aps 50
 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
@@ -751,6 +752,18 @@ set g_balance_arc_beam_range 1000
 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
index ec50bdf508fab90d4bdbd9b12b4ba185d12320a5..07005ccc3f2e8fba8c3eaf6a6ce7f3f5f77b2a1e 100644 (file)
@@ -741,6 +741,7 @@ set g_balance_arc_beam_healing_aps 50
 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
@@ -751,6 +752,18 @@ set g_balance_arc_beam_range 1000
 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
index ec50bdf508fab90d4bdbd9b12b4ba185d12320a5..07005ccc3f2e8fba8c3eaf6a6ce7f3f5f77b2a1e 100644 (file)
@@ -741,6 +741,7 @@ set g_balance_arc_beam_healing_aps 50
 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
@@ -751,6 +752,18 @@ set g_balance_arc_beam_range 1000
 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
index 4ba0766fbada789523c07289203696b734fb7208..b2544fa0740c89e540773baa6b08dd9cd12483c0 100644 (file)
@@ -8161,3 +8161,95 @@ effect rocketminsta_laser_neutral
        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
diff --git a/models/arctrail.mdl b/models/arctrail.mdl
new file mode 100644 (file)
index 0000000..5669bc4
Binary files /dev/null and b/models/arctrail.mdl differ
diff --git a/models/arctrail.mdl_0.skin b/models/arctrail.mdl_0.skin
new file mode 100644 (file)
index 0000000..96ddf30
--- /dev/null
@@ -0,0 +1,2 @@
+Plane01,arc_projectile_core
+Plane02,arc_projectile_long
index dd8d96a5670fbd35ac9ddd0a7d6a10af5a497f12..e5285923e103c4cae9204a0b74cd21f81d467bbc 100644 (file)
@@ -214,6 +214,7 @@ set g_nades_bonus_type 2 "Type of the bonus grenade. 1:normal 2:napalm 3:ice 4:t
 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.)"
index 9ca2a0ab5226f529c42af92c81777f13644c71f0..2ba78f798a1e45816a03043bbcafe2251fc3efe5 100644 (file)
@@ -1192,17 +1192,16 @@ void HUD_Panel_Mouse()
                        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;
 }
index 2082f70b1a3246046544fdff356918c62f311370..4e4f90126a43f7e1326dce264ae4efa303707afc 100644 (file)
@@ -156,8 +156,7 @@ void HUD_Radar_Mouse()
        }
 
 
-       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()
@@ -340,7 +339,7 @@ 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))
index 7682198338308463520b72a815e03e4b8cd91b0d..aa490aa505c21e8c38fc46c52f0813da9b266ed8 100644 (file)
 
 #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
 
@@ -125,7 +177,7 @@ void CSQC_Init()
        }
 
        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)
index bed4daa268dc2a4afbe08995d70d7b3930913ca7..084dfba2f81ae92ca1a577c232b00353dedbf635 100644 (file)
@@ -40,6 +40,13 @@ float gametype;
 
 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
 
index 30c938aa33401debe100ee30941a2196ed04e22d..7071231651b2b69149bbbd2bf226abfe1df95496 100644 (file)
@@ -482,7 +482,7 @@ void MapVote_Draw()
                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)
index 90f6c171c88c621a3b7b72ad3631f62bec7c87e7..63416f2b017cf31cb35a1f58f37c9dc023c186cb 100644 (file)
@@ -531,8 +531,7 @@ void QuickMenu_Mouse()
                }
        }
 
-       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;
 }
index c0f644b806438677380a3ca075b41c303c171cfb..c8e246a06e3dd6a0ab79170802846d19538c37e0 100644 (file)
@@ -294,6 +294,7 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew)
                        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;
index b2302f6d2ebe1ae176504985baec7cac4beccac0..b0445abf18b175b11a0aacdada1f5b81999b14cb 100644 (file)
@@ -200,6 +200,8 @@ const int PROJECTILE_SHAMBLER_LIGHTNING = 33;
 
 const int PROJECTILE_ROCKETMINSTA_LASER = 34;
 
+const int PROJECTILE_ARC_BOLT = 35;
+
 // projectile IDs 40-50 reserved
 
 const int PROJECTILE_RPC = 60;
index b34180056a1a5302c8b0fe46f50c97fe345c8e0e..060367a3c55594b33b46e094196330045bb3f911 100644 (file)
@@ -12,6 +12,7 @@ EFFECT(0, SMOKE_SMALL,              "smoke_small")
 EFFECT(0, SMOKE_LARGE,              "smoke_large")
 
 
+EFFECT(0, ARC_MUZZLEFLASH,          "arc_muzzleflash")
 
 EFFECT(0, BLASTER_IMPACT,           "laser_impact")
 EFFECT(0, BLASTER_MUZZLEFLASH,      "laser_muzzleflash")
@@ -23,6 +24,7 @@ EFFECT(0, ARC_BEAM,                 "arc_beam")
 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")
index 7a0fc66e4ac21666542be1a885cc52da2821abae..56303a44ffa93f36443bf4a3131baa015f361e82 100644 (file)
@@ -8731,3 +8731,145 @@ SUB(arc_overheat_fire) {
 #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';
+}
index ff67a72cdc21a0c5cf398a16de87918200ea64df..dbadc9abbd6eabe1ff1a5bbd8539bd0d247577a5 100644 (file)
        { 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, \
index 006a36308f347c396388c08b453fe8269f1cb90a..7ccbe8fa3fdbf622290ed3864b538cae91fe2f1b 100644 (file)
@@ -1,6 +1,5 @@
 #ifdef SVQC
     #include <common/t_items.qh>
-    #include <server/constants.qh>
 #endif
 
 #include "ammo.qh"
@@ -46,7 +45,7 @@ REGISTER_ITEM(JetpackFuel, Ammo) {
 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
@@ -57,10 +56,7 @@ REGISTER_ITEM(JetpackRegen, Pickup) {
     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
 }
index e93c95ca6077bed5935373c47bf0e1426f4c3315..6a585e68ed9694e1d12bf0e5e713c65f342b2179 100644 (file)
@@ -685,9 +685,7 @@ void HUD_Minigame_Mouse()
        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()
index 354df9a41c40f3e7949ac54f66cbfb13aa2d3935..08aeaaeb7ac975de25bd2c591427d8c3dc28cb99 100644 (file)
@@ -88,6 +88,8 @@ MODEL(PROJECTILE_HOOKBOMB,              "models/grenademodel.md3");
 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
index 9b32642a491a8f065ba9332d702cadf4312b7e99..903237f92b1fd6c86d6216b7667b4d1ece3bf770 100644 (file)
@@ -598,7 +598,6 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerDamage_Calculate)
        // 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))
index 3d91189e2569f094fb5777162e285c3b0690ed2e..408bd6fc853b2aff6411efba26ea27c1bef243e2 100644 (file)
@@ -68,7 +68,6 @@ bool Item_ItemsTime_Allow(GameItem it)
     return (false
     || it.instanceOfPowerup
     || Item_ItemsTime_SpectatorOnly(it)
-    || it == ITEM_JetpackRegen
     );
 }
 
index fcfce9ab77fb5f686013e9d162b874ec618c10ae..3464a7cb349ed824c06b338668b23bfca087467d 100644 (file)
@@ -2,6 +2,12 @@
 
 #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)
 {
@@ -63,8 +69,16 @@ MUTATOR_HOOKFUNCTION(cl_nades, EditProjectile)
 
        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;
@@ -793,7 +807,10 @@ void toss_nade(entity e, vector _velocity, float _time)
        //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);
index a36dc23c2925f0ddb299de38bea4de2c689e6e2f..545b8783bd676a22d1bc44230004f08f9f818317 100644 (file)
     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)
index 96d1a9e7a6b4addb3a0847f0e3714b27ac173cf0..0da3c1df375520f02ab2608b824d6f8afaa4bbe6 100644 (file)
@@ -560,7 +560,7 @@ void CheckWaterJump(entity this)
                #ifdef SVQC
                        PHYS_TELEPORT_TIME(this) = time + 2;    // safety net
                #elif defined(CSQC)
-                       pmove_waterjumptime = time + 2;
+                       pmove_waterjumptime = 2;
                #endif
                }
        }
@@ -1472,8 +1472,10 @@ void PM_Main(entity this)
                PM_Footsteps(this);
        }
 
+#ifdef SVQC
        if(IsFlying(this))
                this.wasFlying = 1;
+#endif
 
        if (IS_PLAYER(this))
                CheckPlayerJump(this);
@@ -1482,10 +1484,17 @@ void PM_Main(entity 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
                }
        }
 
index ba36d8fc98c9c05eaeb82d1983b13e7ef6f35faa..1d3ea78a5bf41c0ae8fa091f87aa9467674259ca 100644 (file)
@@ -17,6 +17,18 @@ CLASS(Arc, Weapon)
 
 #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) \
@@ -45,6 +57,7 @@ CLASS(Arc, Weapon)
         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) \
@@ -156,6 +169,7 @@ bool W_Arc_Beam_Send(entity this, entity to, int sf)
                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
        {
@@ -217,6 +231,77 @@ void Arc_Player_SetHeat(entity player)
        //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)
@@ -227,7 +312,7 @@ void W_Arc_Beam_Think()
 
 
        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;
@@ -243,6 +328,8 @@ void W_Arc_Beam_Think()
                ||
                IS_DEAD(self.owner)
                ||
+               gameover
+               ||
                (!self.owner.BUTTON_ATCK && !burst )
                ||
                STAT(FROZEN, self.owner)
@@ -266,7 +353,8 @@ void W_Arc_Beam_Think()
 
                        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;
                        }
 
@@ -665,8 +753,10 @@ void Arc_Smoke()
                        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)
@@ -681,9 +771,9 @@ void Arc_Smoke()
 
                                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)
                                                {
@@ -695,6 +785,14 @@ void Arc_Smoke()
 
                                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)
                        {
@@ -734,12 +832,22 @@ void Arc_Smoke()
                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))
                {
@@ -759,6 +867,19 @@ void Arc_Smoke()
                }
 #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;
@@ -1202,6 +1323,8 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                {
                        self.beam_usevieworigin = 0;
                }
+
+               self.sv_entnum = ReadByte();
        }
 
        if(!self.beam_usevieworigin)
@@ -1251,11 +1374,13 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
        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);
@@ -1280,7 +1405,7 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                        }
                        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);
@@ -1306,7 +1431,7 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                        }
                        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);
@@ -1332,7 +1457,7 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                        }
                        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);
@@ -1358,7 +1483,7 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                        }
                        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);
@@ -1384,7 +1509,7 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                        }
                        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);
@@ -1410,7 +1535,7 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                        }
                        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);
@@ -1436,7 +1561,7 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                        }
                        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);
index 307b4bd081c6f35cbbfe75eb87925bdd0f44ac2c..9aaf524493719d0171363d086cfd29db0944bf05 100644 (file)
@@ -49,6 +49,7 @@
 #include "linkedlist.qh"
 #include "log.qh"
 #include "map.qh"
+#include "markdown.qh"
 #include "math.qh"
 #include "misc.qh"
 #include "net.qh"
diff --git a/qcsrc/lib/markdown.qh b/qcsrc/lib/markdown.qh
new file mode 100644 (file)
index 0000000..63a4182
--- /dev/null
@@ -0,0 +1,65 @@
+#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
+}
index 00c9982c3db8c8e5d32f77da478dd399432b6803..23897720e3ecf75492058975180c5a4643cd0626 100644 (file)
@@ -163,6 +163,9 @@ void Obituary_SpecialDeath(
                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)
index 9bd602426614ee8107ddf49517e4afc68fa4336d..2a3ef873413981b40c56f0fd8a4b205a91526f61 100644 (file)
@@ -1114,6 +1114,10 @@ void URI_Get_Callback(float id, float status, string data)
                // 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");
index 00d2716e4b6e287b5bdb2ffd9d2f0555fb203460..d81b2b1a5b630c62d0edb78e5c1dd94a6cf6a418 100644 (file)
@@ -846,4 +846,15 @@ MUTATOR_HOOKABLE(MonsterModel, EV_MonsterModel);
 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
index 16847e57df575697f5c4cd0904ef1ff00e705eb8..6273b82bf70ca20fb6b2ad802ad5444815513673 100644 (file)
@@ -1,3 +1,25 @@
+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
diff --git a/textures/projectiles/arc_projectile_core.tga b/textures/projectiles/arc_projectile_core.tga
new file mode 100644 (file)
index 0000000..61ffec1
Binary files /dev/null and b/textures/projectiles/arc_projectile_core.tga differ
diff --git a/textures/projectiles/arc_projectile_core_glow.tga b/textures/projectiles/arc_projectile_core_glow.tga
new file mode 100644 (file)
index 0000000..bf0bd8b
Binary files /dev/null and b/textures/projectiles/arc_projectile_core_glow.tga differ
diff --git a/textures/projectiles/arc_projectile_long.tga b/textures/projectiles/arc_projectile_long.tga
new file mode 100644 (file)
index 0000000..a878dc2
Binary files /dev/null and b/textures/projectiles/arc_projectile_long.tga differ
diff --git a/textures/projectiles/arc_projectile_long_glow.tga b/textures/projectiles/arc_projectile_long_glow.tga
new file mode 100644 (file)
index 0000000..a878dc2
Binary files /dev/null and b/textures/projectiles/arc_projectile_long_glow.tga differ