]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge remote branch 'origin/mirceakitsune/weapon_mine_layer' into fruitiex/fruitbalance
authorFruitieX <rasse@rasse-laptop.(none)>
Tue, 5 Oct 2010 16:28:44 +0000 (19:28 +0300)
committerFruitieX <rasse@rasse-laptop.(none)>
Tue, 5 Oct 2010 16:28:44 +0000 (19:28 +0300)
31 files changed:
balance25.cfg
balanceLeeStricklin.cfg
balanceNexSVN.cfg
balanceSamual.cfg
balanceXonotic.cfg
defaultXonotic.cfg
gfx/crosshairminelayer.tga [new file with mode: 0644]
gfx/hud/default/weaponminelayer.tga [new file with mode: 0644]
gfx/hud/luminos/weaponminelayer.tga [new file with mode: 0644]
gfx/hud/old/weaponminelayer.tga [new file with mode: 0644]
models/mine.md3 [new file with mode: 0644]
models/weapons/g_minelayer.md3 [new file with mode: 0644]
models/weapons/h_minelayer.iqm [new file with mode: 0644]
models/weapons/h_minelayer.iqm.framegroups [new file with mode: 0644]
models/weapons/v_minelayer.md3 [new file with mode: 0644]
qcsrc/client/hud.qc
qcsrc/client/projectile.qc
qcsrc/common/constants.qh
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c
qcsrc/qc-server.cbp
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/cl_weaponsystem.qc
qcsrc/server/defs.qh
qcsrc/server/miscfunctions.qc
qcsrc/server/w_all.qc
qcsrc/server/w_minelayer.qc [new file with mode: 0644]
sound/weapons/mine_det.ogg [new file with mode: 0644]
sound/weapons/mine_exp.ogg [new file with mode: 0644]
sound/weapons/mine_fire.ogg [new file with mode: 0644]
sound/weapons/mine_stick.wav [new file with mode: 0644]
sound/weapons/mine_trigger.wav [new file with mode: 0644]

index 6287460ca329849a946f1ac2e5839451f2fabb1d..0ed48b3e356d53718373dccc9a6832fe821487d1 100644 (file)
@@ -3,6 +3,7 @@ set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide th
 set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
@@ -308,6 +309,28 @@ set g_balance_grenadelauncher_secondary_bouncefactor 0.5
 set g_balance_grenadelauncher_secondary_bouncestop 0.075
 set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
 // }}}
+// {{{ minelayer // TODO
+set g_balance_minelayer_damage 35
+set g_balance_minelayer_edgedamage 30
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 750
+set g_balance_minelayer_lifetime 60
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 5
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 4 // 0 disables the limit
+set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
+// }}}
 // {{{ electro
 set g_balance_electro_lightning 0
 set g_balance_electro_primary_damage 65
index c1ff936126ba31177bac603eb64366dd10bc250f..20c6153a1e8d72423442154c11d2575fc94cc047 100644 (file)
@@ -13,6 +13,7 @@ set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide th
 set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
@@ -319,6 +320,28 @@ set g_balance_grenadelauncher_secondary_bouncefactor 0.7
 set g_balance_grenadelauncher_secondary_bouncestop 0.12
 set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
 // }}}
+// {{{ minelayer // TODO
+set g_balance_minelayer_damage 35
+set g_balance_minelayer_edgedamage 30
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 750
+set g_balance_minelayer_lifetime 60
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 5
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 4 // 0 disables the limit
+set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
+// }}}
 // {{{ electro
 set g_balance_electro_lightning 0
 set g_balance_electro_primary_damage 80
index 36615d790cbb7c6d12e55c5ba3ac076b61d6fb75..82b0cfc50147f8741e5069d9504e33dfc167c13e 100644 (file)
@@ -3,6 +3,7 @@ set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide th
 set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
@@ -307,6 +308,28 @@ set g_balance_grenadelauncher_secondary_bouncefactor 0.5
 set g_balance_grenadelauncher_secondary_bouncestop 0.075
 set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
 // }}}
+// {{{ minelayer // TODO
+set g_balance_minelayer_damage 35
+set g_balance_minelayer_edgedamage 30
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 750
+set g_balance_minelayer_lifetime 60
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 5
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 4 // 0 disables the limit
+set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
+// }}}
 // {{{ electro
 set g_balance_electro_lightning 0
 set g_balance_electro_primary_damage 65
index aeed47e8986b05e972cc96bc387cf511d8a20a7d..4c9095a1ad7a51e8c49bb328d4343249030c8514 100644 (file)
@@ -3,6 +3,7 @@ set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide th
 set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
@@ -308,6 +309,28 @@ set g_balance_grenadelauncher_secondary_bouncefactor 0.5
 set g_balance_grenadelauncher_secondary_bouncestop 0.075
 set g_balance_grenadelauncher_secondary_remote_detonateprimary 1
 // }}}
+// {{{ minelayer // TODO
+set g_balance_minelayer_damage 35
+set g_balance_minelayer_edgedamage 30
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 750
+set g_balance_minelayer_lifetime 60
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 5
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 4 // 0 disables the limit
+set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
+// }}}
 // {{{ electro
 set g_balance_electro_lightning 0
 set g_balance_electro_primary_damage 65
index e28bd844dec4d0d9214cdd7f5bdaa54f4c522232..0f25b89947aed72b99206f21843909c1d9000179 100644 (file)
@@ -3,6 +3,7 @@ set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide th
 set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
 set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
@@ -308,6 +309,28 @@ set g_balance_grenadelauncher_secondary_bouncefactor 0.5
 set g_balance_grenadelauncher_secondary_bouncestop 0.12
 set g_balance_grenadelauncher_secondary_remote_detonateprimary 1
 // }}}
+// {{{ minelayer // TODO
+set g_balance_minelayer_damage 35
+set g_balance_minelayer_edgedamage 30
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 750
+set g_balance_minelayer_lifetime 60
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 5
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 4 // 0 disables the limit
+set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
+// }}}
 // {{{ electro // TODO
 set g_balance_electro_lightning 1
 set g_balance_electro_primary_damage 85
index 946d0a440460edc7a9e1508d460e48f66e4ff0c1..df1a85857068b6b8ee5b7afcf9fcc0ed79e2f6bb 100644 (file)
@@ -119,6 +119,12 @@ seta crosshair_grenadelauncher_color_green 0.15    "crosshair color green component
 seta crosshair_grenadelauncher_color_blue 0    "crosshair color blue component to display when wielding the mortar"
 seta crosshair_grenadelauncher_color_alpha 1.15        "crosshair alpha value to display when wielding the mortar"
 seta crosshair_grenadelauncher_size 0.7        "crosshair size when wielding the mortar"
+seta crosshair_minelayer ""    "crosshair to display when wielding the mortar"
+seta crosshair_minelayer_color_red 0.75        "crosshair color red component to display when wielding the mortar"
+seta crosshair_minelayer_color_green 0.75      "crosshair color green component to display when wielding the mortar"
+seta crosshair_minelayer_color_blue 0  "crosshair color blue component to display when wielding the mortar"
+seta crosshair_minelayer_color_alpha 1.15      "crosshair alpha value to display when wielding the mortar"
+seta crosshair_minelayer_size 0.9      "crosshair size when wielding the mortar"
 seta crosshair_electro ""      "crosshair to display when wielding the electro"
 seta crosshair_electro_color_red 0.35  "crosshair color red component to display when wielding the electro"
 seta crosshair_electro_color_green 0.5 "crosshair color green component to display when wielding the electro"
@@ -428,9 +434,9 @@ set bot_ai_keyboard_treshold 0.57
 set bot_ai_aimskill_offset 0.3 "Amount of error induced to the bots aim"
 set bot_ai_aimskill_think 1 "Aiming velocity. Use values below 1 for slower aiming"
 set bot_ai_custom_weapon_priority_distances "300 850"  "Define close and far distances in any order. Based on the distance to the enemy bots will choose different weapons"
-set bot_ai_custom_weapon_priority_far   "minstanex nex campingrifle rocketlauncher grenadelauncher electro hagar hlac crylink laser uzi fireball seeker shotgun tuba"  "Desired weapons for far distances ordered by priority"
-set bot_ai_custom_weapon_priority_mid   "minstanex rocketlauncher nex fireball seeker grenadelauncher electro uzi campingrifle crylink hlac hagar shotgun laser tuba"  "Desired weapons for middle distances ordered by priority"
-set bot_ai_custom_weapon_priority_close "minstanex nex uzi hlac tuba seeker hagar crylink grenadelauncher shotgun electro campingrifle rocketlauncher laser fireball"  "Desired weapons for close distances ordered by priority"
+set bot_ai_custom_weapon_priority_far   "minstanex nex campingrifle rocketlauncher minelayer grenadelauncher electro hagar hlac crylink laser uzi fireball seeker shotgun tuba"        "Desired weapons for far distances ordered by priority"
+set bot_ai_custom_weapon_priority_mid   "minstanex rocketlauncher nex fireball seeker minelayer grenadelauncher electro uzi campingrifle crylink hlac hagar shotgun laser tuba"        "Desired weapons for middle distances ordered by priority"
+set bot_ai_custom_weapon_priority_close "minstanex nex uzi hlac tuba seeker hagar crylink minelayer grenadelauncher shotgun electro campingrifle rocketlauncher laser fireball"        "Desired weapons for close distances ordered by priority"
 set bot_ai_weapon_combo 1      "Enable bots to do weapon combos"
 set bot_ai_weapon_combo_threshold 0.3  "Try to make a combo N seconds after the last attack"
 set bot_ai_friends_aware_pickup_radius "500"   "Bots will not pickup items if a team mate is this distance near the item"
@@ -1546,13 +1552,13 @@ set g_jump_grunt 0      "Do you make a grunting noise every time you jump? Is it the
 
 alias allready "sv_cmd allready"
 
-seta cl_weaponpriority "minstanex rocketlauncher nex grenadelauncher fireball hlac hagar seeker crylink campingrifle uzi electro tuba shotgun laser hook porto" "weapon priority list"
+seta cl_weaponpriority "minstanex rocketlauncher nex minelayer grenadelauncher fireball hlac hagar seeker crylink campingrifle uzi electro tuba shotgun laser hook porto" "weapon priority list"
 seta cl_weaponpriority_useforcycling 0 "when set, weapon cycling by the mouse wheel makes use of the weapon priority list (the special value 2 uses the weapon ID list for cycling)"
 seta cl_weaponpriority0 "rocketlauncher grenadelauncher hagar seeker fireball" "use impulse 200 for prev gun from this list, 210 for best gun, 220 for next gun.  Default value: explosives"
 seta cl_weaponpriority1 "minstanex nex crylink hlac electro laser"             "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun.  Default value: energy"
 seta cl_weaponpriority2 "minstanex nex campingrifle"                           "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun.  Default value: hitscan exact"
 seta cl_weaponpriority3 "minstanex nex campingrifle uzi shotgun"               "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun.  Default value: hitscan all"
-seta cl_weaponpriority4 "grenadelauncher hlac hagar crylink seeker shotgun"    "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun.  Default value: spam weapons"
+seta cl_weaponpriority4 "minelayer grenadelauncher hlac hagar crylink seeker shotgun"    "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun.  Default value: spam weapons"
 seta cl_weaponpriority5 "laser hook porto"                                     "use impulse 205 for prev gun from this list, 215 for best gun, 225 for next gun.  Default value: weapons for moving"
 seta cl_weaponpriority6 "" "use impulse 206 for prev gun from this list, 216 for best gun, 226 for next gun"
 seta cl_weaponpriority7 "" "use impulse 207 for prev gun from this list, 217 for best gun, 227 for next gun"
@@ -1892,6 +1898,7 @@ cl_decals_newsystem 1
 set g_weaponreplace_laser ""
 set g_weaponreplace_shotgun ""
 set g_weaponreplace_uzi ""
+set g_weaponreplace_minelayer ""
 set g_weaponreplace_grenadelauncher ""
 set g_weaponreplace_electro ""
 set g_weaponreplace_crylink ""
diff --git a/gfx/crosshairminelayer.tga b/gfx/crosshairminelayer.tga
new file mode 100644 (file)
index 0000000..e869ab5
Binary files /dev/null and b/gfx/crosshairminelayer.tga differ
diff --git a/gfx/hud/default/weaponminelayer.tga b/gfx/hud/default/weaponminelayer.tga
new file mode 100644 (file)
index 0000000..3fbccf9
Binary files /dev/null and b/gfx/hud/default/weaponminelayer.tga differ
diff --git a/gfx/hud/luminos/weaponminelayer.tga b/gfx/hud/luminos/weaponminelayer.tga
new file mode 100644 (file)
index 0000000..3fbccf9
Binary files /dev/null and b/gfx/hud/luminos/weaponminelayer.tga differ
diff --git a/gfx/hud/old/weaponminelayer.tga b/gfx/hud/old/weaponminelayer.tga
new file mode 100644 (file)
index 0000000..444247f
Binary files /dev/null and b/gfx/hud/old/weaponminelayer.tga differ
diff --git a/models/mine.md3 b/models/mine.md3
new file mode 100644 (file)
index 0000000..7758e3e
Binary files /dev/null and b/models/mine.md3 differ
diff --git a/models/weapons/g_minelayer.md3 b/models/weapons/g_minelayer.md3
new file mode 100644 (file)
index 0000000..f0dce9d
Binary files /dev/null and b/models/weapons/g_minelayer.md3 differ
diff --git a/models/weapons/h_minelayer.iqm b/models/weapons/h_minelayer.iqm
new file mode 100644 (file)
index 0000000..0c6ed41
Binary files /dev/null and b/models/weapons/h_minelayer.iqm differ
diff --git a/models/weapons/h_minelayer.iqm.framegroups b/models/weapons/h_minelayer.iqm.framegroups
new file mode 100644 (file)
index 0000000..0a59625
--- /dev/null
@@ -0,0 +1,4 @@
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
diff --git a/models/weapons/v_minelayer.md3 b/models/weapons/v_minelayer.md3
new file mode 100644 (file)
index 0000000..5d06b3c
Binary files /dev/null and b/models/weapons/v_minelayer.md3 differ
index c1dbede921a44231d5f157cf383d697b23dd248d..0f54a2857f578fe96fedd305bba7663a7aa903ee 100644 (file)
@@ -1478,6 +1478,7 @@ float GetAmmoTypeForWep(float i)
                case WEP_UZI: return 1;
                case WEP_CAMPINGRIFLE: return 1;
                case WEP_GRENADE_LAUNCHER: return 2;
+               case WEP_MINE_LAYER: return 2;
                case WEP_ELECTRO: return 3;
                case WEP_CRYLINK: return 3;
                case WEP_HLAC: return 3;
index 9a773379b5d6eed97a57ae1189f2651ffc6c67d8..39aabc44adf4a430f357c0e6e82d4a6d07e596ef 100644 (file)
@@ -279,6 +279,7 @@ void Ent_Projectile()
                        case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
                        case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
                        case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
+                       case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum(""); break;
                        case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break;
                        case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(""); break;
                        case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
@@ -330,6 +331,10 @@ void Ent_Projectile()
                                self.move_bounce_factor = g_balance_grenadelauncher_secondary_bouncefactor;
                                self.move_bounce_stopspeed = g_balance_grenadelauncher_secondary_bouncestop;
                                break;
+                       case PROJECTILE_MINE:
+                               self.mins = '-4 -4 -4';
+                               self.maxs = '4 4 4';
+                               break;
                        case PROJECTILE_PORTO_RED:
                                self.colormod = '2 1 1';
                                self.alphamod = 0.5;
@@ -407,6 +412,7 @@ void Projectile_Precache()
        precache_model("models/ebomb.mdl");
        precache_model("models/elaser.mdl");
        precache_model("models/grenademodel.md3");
+       precache_model("models/mine.md3");
        precache_model("models/hagarmissile.mdl");
        precache_model("models/hlac_bullet.md3");
        precache_model("models/laser.mdl");
index 6c16097fcbea21ccf9602797d6e099137a20b9e2..5e8dff7dca2645fb81564d3c243c09381ca15a9d 100644 (file)
@@ -456,20 +456,21 @@ float PROJECTILE_CRYLINK = 5;
 float PROJECTILE_ELECTRO_BEAM = 6;
 float PROJECTILE_GRENADE = 7;
 float PROJECTILE_GRENADE_BOUNCING = 8;
-float PROJECTILE_LASER = 9;
-float PROJECTILE_HLAC = 10;
-float PROJECTILE_SEEKER = 11;
-float PROJECTILE_FLAC = 12;
-float PROJECTILE_PORTO_RED = 13;
-float PROJECTILE_PORTO_BLUE = 14;
-float PROJECTILE_HOOKBOMB = 15;
-float PROJECTILE_HAGAR = 16;
-float PROJECTILE_HAGAR_BOUNCING = 17;
-float PROJECTILE_BULLET_GLOWING = 18;
-float PROJECTILE_CRYLINK_BOUNCING = 19;
-float PROJECTILE_FIREBALL = 20;
-float PROJECTILE_FIREMINE = 21;
-float PROJECTILE_BULLET_GLOWING_TRACER = 22;
+float PROJECTILE_MINE = 9;
+float PROJECTILE_LASER = 10;
+float PROJECTILE_HLAC = 11;
+float PROJECTILE_SEEKER = 12;
+float PROJECTILE_FLAC = 13;
+float PROJECTILE_PORTO_RED = 14;
+float PROJECTILE_PORTO_BLUE = 15;
+float PROJECTILE_HOOKBOMB = 16;
+float PROJECTILE_HAGAR = 17;
+float PROJECTILE_HAGAR_BOUNCING = 18;
+float PROJECTILE_BULLET_GLOWING = 19;
+float PROJECTILE_CRYLINK_BOUNCING = 20;
+float PROJECTILE_FIREBALL = 21;
+float PROJECTILE_FIREMINE = 22;
+float PROJECTILE_BULLET_GLOWING_TRACER = 23;
 
 float SPECIES_HUMAN        =  0;
 float SPECIES_ROBOT_SOLID  =  1;
index 517f68bd311b7ee10176b8f8ab1e9b8a65127905..c0d16a959727cb2c7bf3de5b980153b7eba124ea 100644 (file)
@@ -268,7 +268,7 @@ void XonoticMutatorsDialog_fill(entity me)
                me.TDempty(me, 0.2);
                me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_start_weapon_laser", "0", "No start weapons"));
                        e.cvarOffValue = "-1";
-                       makeMulti(e, "g_start_weapon_shotgun g_start_weapon_uzi g_start_weapon_grenadelauncher g_start_weapon_electro g_start_weapon_crylink g_start_weapon_nex g_start_weapon_hagar g_start_weapon_rocketlauncher g_start_weapon_campingrifle g_start_weapon_hlac g_start_weapon_seeker g_start_weapon_minstanex g_start_weapon_hook g_start_weapon_porto g_start_weapon_tuba");
+                       makeMulti(e, "g_start_weapon_shotgun g_start_weapon_uzi g_start_weapon_grenadelauncher g_start_weapon_minelayer g_start_weapon_electro g_start_weapon_crylink g_start_weapon_nex g_start_weapon_hagar g_start_weapon_rocketlauncher g_start_weapon_campingrifle g_start_weapon_hlac g_start_weapon_seeker g_start_weapon_minstanex g_start_weapon_hook g_start_weapon_porto g_start_weapon_tuba");
 
        me.gotoRC(me, me.rows - 1, 0);
                me.TD(me, 1, me.columns, e = makeXonoticButton("OK", '0 0 0'));
index 00912bea3389eb6347f9f18bd68416a2ea975f99..eaa30d2d46ae4ca1d4936fe77220542541c1dad9 100644 (file)
                <Unit filename="w_electro.qc" />
                <Unit filename="w_fireball.qc" />
                <Unit filename="w_grenadelauncher.qc" />
+               <Unit filename="w_minelayer.qc" />
                <Unit filename="w_hagar.qc" />
                <Unit filename="w_hlac.qc" />
                <Unit filename="w_hook.qc" />
index 2b86c27ad0b3c6949c4f1ccc109260d601737edb..934aba87ddc6fd2f175fcbde18459dc3de57f694 100644 (file)
@@ -950,6 +950,7 @@ void havocbot_chooseweapon()
        local float nex     ; nex      =-1000;
        local float hagar   ; hagar    =-1000;
        local float grenade ; grenade  =-1000;
+       local float mine    ; mine     =-1000;
        local float electro ; electro  =-1000;
        local float crylink ; crylink  =-1000;
        local float uzi     ; uzi      =-1000;
@@ -1077,6 +1078,15 @@ void havocbot_chooseweapon()
                grenade = (cvar("g_balance_grenadelauncher_primary_damage")/cvar("g_balance_grenadelauncher_primary_refire")*1.0)
                        * bound(0,(cvar("g_balance_grenadelauncher_primary_speed")/distance*maxdelaytime),1)*1.1;
 
+       if (client_hasweapon(self, WEP_MINE_LAYER, TRUE, FALSE) &&
+               !(
+                       cvar("bot_ai_weapon_combo") && self.weapon == WEP_MINE_LAYER &&
+                       af > combo_time
+               )
+       )
+               mine = (cvar("g_balance_minelayer_damage")/cvar("g_balance_minelayer_refire")*1.0)
+                       * bound(0,(cvar("g_balance_minelayer_speed")/distance*maxdelaytime),1)*1.1;
+
        if (client_hasweapon(self, WEP_ELECTRO, TRUE, FALSE) &&
                !(      cvar("bot_ai_weapon_combo") && self.weapon == WEP_ELECTRO &&
                        af > combo_time
@@ -1123,6 +1133,7 @@ void havocbot_chooseweapon()
        dprint("Nex: "    , ftos(nex     ), "\n");
        dprint("Hagar: "  , ftos(hagar   ), "\n");
        dprint("Grenade: ", ftos(grenade ), "\n");
+       dprint("Mine: "   , ftos(mine    ), "\n");
        dprint("Electro: ", ftos(electro ), "\n");
        dprint("Crylink: ", ftos(crylink ), "\n");
        dprint("Uzi: "    , ftos(uzi     ), "\n");
@@ -1135,6 +1146,7 @@ void havocbot_chooseweapon()
        w = WEP_NEX              ;s = nex      ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
        w = WEP_HAGAR            ;s = hagar    ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
        w = WEP_GRENADE_LAUNCHER ;s = grenade  ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+       w = WEP_MINE_LAYER       ;s = mine     ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
        w = WEP_ELECTRO          ;s = electro  ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
        w = WEP_CRYLINK          ;s = crylink  ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
        w = WEP_UZI              ;s = uzi      ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
index 925d53fa7e3cc218cfeba460f432969db25d7a47..c9a5dfc4aa1b9d61236355e94824506004053edb 100644 (file)
@@ -981,6 +981,13 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
                                self = cl;
                                f = weapon_action(wpn, WR_CHECKAMMO1);
                                f = f + weapon_action(wpn, WR_CHECKAMMO2);
+
+                               // always allow selecting the Mine Layer if we placed mines, so that we can detonate them
+                               local entity mine;
+                               if(wpn == WEP_MINE_LAYER)
+                               for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+                                       f = 1;
+
                                self = oldself;
                        }
                        if (!f)
@@ -1093,6 +1100,12 @@ float weapon_prepareattack_checkammo(float secondary)
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
        if (!weapon_action(self.weapon, WR_CHECKAMMO1 + secondary))
        {
+               // always keep the Mine Layer if we placed mines, so that we can detonate them
+               local entity mine;
+               if(self.weapon == WEP_MINE_LAYER)
+               for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+                       return FALSE;
+
                W_SwitchToOtherWeapon(self);
                return FALSE;
        }
index f084e18d4b0b69f6a92b5009321e419e583145c5..47f514c32b07096e485bb994fc1be4b2090214f9 100644 (file)
@@ -294,6 +294,7 @@ string getTimeoutText(float addOneSecond);
 .entity flagcarried;
 
 .entity lastrocket;
+.entity lastmine;
 
 .float playerid;
 float playerid_last;
index 3db4e47be8d2e154732916bda9d1de44bee0cad8..d4232424072f84aa90d2c7fd220371e4a91aa923 100644 (file)
@@ -989,7 +989,7 @@ void readplayerstartcvars()
        if (g_weaponarena)
        {
                start_weapons = g_weaponarena;
-               if (g_weaponarena & (WEPBIT_GRENADE_LAUNCHER | WEPBIT_HAGAR | WEPBIT_ROCKET_LAUNCHER))
+               if (g_weaponarena & (WEPBIT_GRENADE_LAUNCHER | WEPBIT_MINE_LAYER | WEPBIT_HAGAR | WEPBIT_ROCKET_LAUNCHER))
                        start_ammo_rockets = 999;
                if (g_weaponarena & WEPBIT_SHOTGUN)
                        start_ammo_shells = 999;
index 9a9b3830244602e00861704efe6716a2229f6304..83fc8acb5de47e9f58406588fdebce20099ba899 100644 (file)
@@ -2,6 +2,7 @@
 #include "w_shotgun.qc"
 #include "w_uzi.qc"
 #include "w_grenadelauncher.qc"
+#include "w_minelayer.qc"
 #include "w_electro.qc"
 #include "w_crylink.qc"
 #include "w_nex.qc"
diff --git a/qcsrc/server/w_minelayer.qc b/qcsrc/server/w_minelayer.qc
new file mode 100644 (file)
index 0000000..7342d1e
--- /dev/null
@@ -0,0 +1,450 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(MINE_LAYER, w_minelayer, IT_ROCKETS, 4, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_HIGH, "minelayer", "minelayer", "Mine Layer");
+#else
+#ifdef SVQC
+.float minelayer_detonate, minelayer_mines;
+.float mine_time;
+
+void spawnfunc_weapon_minelayer (void)
+{
+       weapon_defaultspawnfunc(WEP_MINE_LAYER);
+}
+
+void W_Mine_Stick ()
+{
+       spamsound (self, CHAN_PROJECTILE, "weapons/mine_stick.wav", VOL_BASE, ATTN_NORM);
+
+       // in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile
+
+       local entity newmine;
+       newmine = spawn();
+       newmine.classname = self.classname;
+
+       newmine.bot_dodge = self.bot_dodge;
+       newmine.bot_dodgerating = self.bot_dodgerating;
+
+       newmine.owner = self.owner;
+       setsize(newmine, '-4 -4 -4', '4 4 4');
+       setorigin(newmine, self.origin);
+       setmodel(newmine, "models/mine.md3");
+       newmine.angles = vectoangles(-trace_plane_normal); // face against the surface
+
+       newmine.takedamage = self.takedamage;
+       newmine.damageforcescale = self.damageforcescale;
+       newmine.health = self.health;
+       newmine.event_damage = self.event_damage;
+
+       newmine.movetype = MOVETYPE_NONE; // lock the mine in place
+       newmine.projectiledeathtype = self.projectiledeathtype;
+
+       newmine.mine_time = self.mine_time;
+
+       newmine.touch = SUB_Null;
+       newmine.think = self.think;
+       newmine.nextthink = time;
+       newmine.cnt = self.cnt;
+       newmine.flags = self.flags;
+
+       remove(self);
+       self = newmine;
+}
+
+void W_Mine_Explode ()
+{
+       if(other.takedamage == DAMAGE_AIM)
+               if(other.classname == "player")
+                       if(IsDifferentTeam(self.owner, other))
+                               if(IsFlying(other))
+                                       AnnounceTo(self.owner, "airshot");
+
+       self.event_damage = SUB_Null;
+       self.takedamage = DAMAGE_NO;
+
+       RadiusDamage (self, self.owner, cvar("g_balance_minelayer_damage"), cvar("g_balance_minelayer_edgedamage"), cvar("g_balance_minelayer_radius"), world, cvar("g_balance_minelayer_force"), self.projectiledeathtype, other);
+
+       if (self.owner.weapon == WEP_MINE_LAYER)
+       {
+               if(self.owner.ammo_rockets < cvar("g_balance_minelayer_ammo"))
+               {
+                       self.owner.cnt = WEP_MINE_LAYER;
+                       ATTACK_FINISHED(self.owner) = time;
+                       self.owner.switchweapon = w_getbestweapon(self.owner);
+               }
+       }
+       remove (self);
+}
+
+void W_Mine_DoRemoteExplode ()
+{
+       self.event_damage = SUB_Null;
+       self.takedamage = DAMAGE_NO;
+
+       RadiusDamage (self, self.owner, cvar("g_balance_minelayer_remote_damage"), cvar("g_balance_minelayer_remote_edgedamage"), cvar("g_balance_minelayer_remote_radius"), world, cvar("g_balance_minelayer_remote_force"), self.projectiledeathtype | HITTYPE_BOUNCE, world);
+
+       if (self.owner.weapon == WEP_MINE_LAYER)
+       {
+               if(self.owner.ammo_rockets < cvar("g_balance_minelayer_ammo"))
+               {
+                       self.owner.cnt = WEP_MINE_LAYER;
+                       ATTACK_FINISHED(self.owner) = time;
+                       self.owner.switchweapon = w_getbestweapon(self.owner);
+               }
+       }
+       remove (self);
+}
+
+void W_Mine_RemoteExplode ()
+{
+       if(self.owner.deadflag == DEAD_NO)
+               if((self.spawnshieldtime >= 0)
+                       ? (time >= self.spawnshieldtime) // timer
+                       : (vlen(NearestPointOnBox(self.owner, self.origin) - self.origin) > cvar("g_balance_minelayer_radius")) // safety device
+               )
+               {
+                       W_Mine_DoRemoteExplode();
+               }
+}
+
+void W_Mine_ProximityExplode ()
+{
+       // make sure no friend is in the mine's radius. If there is any, explosion is delayed until he's at a safe distance
+       if(cvar("g_balance_minelayer_protection"))
+       {
+               entity head;
+               head = findradius(self.origin, cvar("g_balance_minelayer_radius"));
+               while(head)
+               {
+                       if(head == self.owner || !IsDifferentTeam(head, self.owner))
+                               return;
+                       head = head.chain;
+               }
+       }
+
+       self.mine_time = 0;
+       W_Mine_Explode();
+}
+
+void W_Mine_Think (void)
+{
+       entity head;
+
+       self.nextthink = time;
+       if (time > self.cnt)
+       {
+               other = world;
+               self.projectiledeathtype |= HITTYPE_BOUNCE;
+               W_Mine_Explode();
+               return;
+       }
+
+       // a player's mines shall explode if he disconnects or dies
+       // TODO: Do this on team change too
+       if(self.owner.classname != "player" || self.owner.deadflag != DEAD_NO)
+       {
+               other = world;
+               self.projectiledeathtype |= HITTYPE_BOUNCE;
+               W_Mine_Explode();
+               return;
+       }
+
+       // set the mine for detonation when a foe gets close enough
+       head = findradius(self.origin, cvar("g_balance_minelayer_proximityradius"));
+       while(head)
+       {
+               if(head.classname == "player" && head.deadflag == DEAD_NO)
+               if(head != self.owner && IsDifferentTeam(head, self.owner)) // don't trigger for team mates
+               if(!self.mine_time)
+               {
+                       spamsound (self, CHAN_PROJECTILE, "weapons/mine_trigger.wav", VOL_BASE, ATTN_NORM);
+                       self.mine_time = time + cvar("g_balance_minelayer_time");
+               }
+               head = head.chain;
+       }
+
+       // explode if it's time to
+       if(self.mine_time && time >= self.mine_time)
+               W_Mine_ProximityExplode();
+
+       // remote detonation
+       if (self.owner.weapon == WEP_MINE_LAYER)
+       if (self.owner.deadflag == DEAD_NO)
+       if (self.minelayer_detonate)
+               W_Mine_RemoteExplode();
+
+       if(self.csqcprojectile_clientanimate == 0)
+               UpdateCSQCProjectile(self);
+}
+
+void W_Mine_Touch (void)
+{
+       PROJECTILE_TOUCH;
+       if(!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))
+               W_Mine_Stick();
+       else if(self.movetype != MOVETYPE_NONE) // don't unstick a locked mine when someone touches it
+               self.velocity = '0 0 0';
+}
+
+void W_Mine_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+       if (self.health <= 0)
+               return;
+       self.health = self.health - damage;
+       self.angles = vectoangles(self.velocity);
+       if (self.health <= 0)
+               W_PrepareExplosionByDamage(attacker, W_Mine_Explode);
+}
+
+void W_Mine_Attack (void)
+{
+       local entity mine;
+       local entity flash;
+
+       // scan how many mines we placed, and return if we reached our limit
+       if(cvar("g_balance_minelayer_limit"))
+       {
+               self.minelayer_mines = 0;
+               for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+                       self.minelayer_mines += 1;
+
+               if(self.minelayer_mines >= cvar("g_balance_minelayer_limit"))
+               {
+                       // the refire delay keeps this message from being spammed
+                       sprint(self, strcat("You cannot place more than ^2", cvar_string("g_balance_minelayer_limit"), " ^7mines at a time\n") );
+                       play2(self, "weapons/unavailable.wav");
+                       return;
+               }
+       }
+
+       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+               self.ammo_rockets = self.ammo_rockets - cvar("g_balance_minelayer_ammo");
+
+       W_SetupShot_ProjectileSize (self, '-4 -4 -4', '4 4 4', FALSE, 5, "weapons/mine_fire.wav", cvar("g_balance_minelayer_damage"));
+       pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+       mine = WarpZone_RefSys_SpawnSameRefSys(self);
+       mine.owner = self;
+       if(cvar("g_balance_minelayer_detonatedelay") >= 0)
+               mine.spawnshieldtime = time + cvar("g_balance_minelayer_detonatedelay");
+       else
+               mine.spawnshieldtime = -1;
+       mine.classname = "mine";
+       mine.bot_dodge = TRUE;
+       mine.bot_dodgerating = cvar("g_balance_minelayer_damage") * 2; // * 2 because it can detonate inflight which makes it even more dangerous
+
+       mine.takedamage = DAMAGE_YES;
+       mine.damageforcescale = cvar("g_balance_minelayer_damageforcescale");
+       mine.health = cvar("g_balance_minelayer_health");
+       mine.event_damage = W_Mine_Damage;
+
+       mine.movetype = MOVETYPE_TOSS;
+       PROJECTILE_MAKETRIGGER(mine);
+       mine.projectiledeathtype = WEP_MINE_LAYER;
+       setsize (mine, '-4 -4 -4', '4 4 4'); // give it some size so it can be shot
+
+       setorigin (mine, w_shotorg - v_forward * 4); // move it back so it hits the wall at the right point
+       W_SetupProjectileVelocity(mine, cvar("g_balance_minelayer_speed"), 0);
+       mine.angles = vectoangles (mine.velocity);
+
+       mine.touch = W_Mine_Touch;
+       mine.think = W_Mine_Think;
+       mine.nextthink = time;
+       mine.cnt = time + cvar("g_balance_minelayer_lifetime");
+       mine.flags = FL_PROJECTILE;
+
+       CSQCProjectile(mine, FALSE, PROJECTILE_MINE, TRUE);
+
+       // muzzle flash for 1st person view
+       flash = spawn ();
+       setmodel (flash, "models/flash.md3"); // precision set below
+       SUB_SetFade (flash, time, 0.1);
+       flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
+       W_AttachToShotorg(flash, '5 0 0');
+
+       // common properties
+}
+
+void spawnfunc_weapon_minelayer (void); // defined in t_items.qc
+
+float w_minelayer(float req)
+{
+       entity mine;
+       float minfound;
+       if (req == WR_AIM)
+       {
+               // aim and decide to fire if appropriate
+               self.BUTTON_ATCK = bot_aim(cvar("g_balance_minelayer_speed"), 0, cvar("g_balance_minelayer_lifetime"), FALSE);
+               if(skill >= 2) // skill 0 and 1 bots won't detonate mines!
+               {
+                       // decide whether to detonate mines
+                       local entity mine, targetlist, targ;
+                       local float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
+                       local float selfdamage, teamdamage, enemydamage;
+                       edgedamage = cvar("g_balance_minelayer_edgedamage");
+                       coredamage = cvar("g_balance_minelayer_damage");
+                       edgeradius = cvar("g_balance_minelayer_radius");
+                       recipricoledgeradius = 1 / edgeradius;
+                       selfdamage = 0;
+                       teamdamage = 0;
+                       enemydamage = 0;
+                       targetlist = findchainfloat(bot_attack, TRUE);
+                       mine = find(world, classname, "mine");
+                       while (mine)
+                       {
+                               if (mine.owner != self)
+                               {
+                                       mine = find(mine, classname, "mine");
+                                       continue;
+                               }
+                               targ = targetlist;
+                               while (targ)
+                               {
+                                       d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - mine.origin);
+                                       d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
+                                       // count potential damage according to type of target
+                                       if (targ == self)
+                                               selfdamage = selfdamage + d;
+                                       else if (targ.team == self.team && teams_matter)
+                                               teamdamage = teamdamage + d;
+                                       else if (bot_shouldattack(targ))
+                                               enemydamage = enemydamage + d;
+                                       targ = targ.chain;
+                               }
+                               mine = find(mine, classname, "mine");
+                       }
+                       local float desirabledamage;
+                       desirabledamage = enemydamage;
+                       if (teamplay != 1 && time > self.invincible_finished && time > self.spawnshieldtime)
+                               desirabledamage = desirabledamage - selfdamage * cvar("g_balance_selfdamagepercent");
+                       if (self.team && teamplay != 1)
+                               desirabledamage = desirabledamage - teamdamage;
+
+                       mine = find(world, classname, "mine");
+                       while (mine)
+                       {
+                               if (mine.owner != self)
+                               {
+                                       mine = find(mine, classname, "mine");
+                                       continue;
+                               }
+                               makevectors(mine.v_angle);
+                               targ = targetlist;
+                               if (skill > 9) // normal players only do this for the target they are tracking
+                               {
+                                       targ = targetlist;
+                                       while (targ)
+                                       {
+                                               if (
+                                                       (v_forward * normalize(mine.origin - targ.origin)< 0.1)
+                                                       && desirabledamage > 0.1*coredamage
+                                               )self.BUTTON_ATCK2 = TRUE;
+                                               targ = targ.chain;
+                                       }
+                               }else{
+                                       local float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
+                                       //As the distance gets larger, a correct detonation gets near imposible
+                                       //Bots are assumed to use the mine spawnfunc_light to see if the mine gets near a player
+                                       if(v_forward * normalize(mine.origin - self.enemy.origin)< 0.1)
+                                               if(self.enemy.classname == "player")
+                                                       if(desirabledamage >= 0.1*coredamage)
+                                                               if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1))
+                                                                       self.BUTTON_ATCK2 = TRUE;
+                               //      dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n");
+                               }
+
+                               mine = find(mine, classname, "mine");
+                       }
+                       // if we would be doing at X percent of the core damage, detonate it
+                       // but don't fire a new shot at the same time!
+                       if (desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events
+                               self.BUTTON_ATCK2 = TRUE;
+                       if ((skill > 6.5) && (selfdamage > self.health))
+                               self.BUTTON_ATCK2 = FALSE;
+                       //if(self.BUTTON_ATCK2 == TRUE)
+                       //      dprint(ftos(desirabledamage),"\n");
+                       if (self.BUTTON_ATCK2 == TRUE) self.BUTTON_ATCK = FALSE;
+               }
+       }
+       else if (req == WR_THINK)
+       {
+               if (self.BUTTON_ATCK)
+               {
+                       if(weapon_prepareattack(0, cvar("g_balance_minelayer_refire")))
+                       {
+                               W_Mine_Attack();
+                               weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_minelayer_animtime"), w_ready);
+                       }
+               }
+
+               if (self.BUTTON_ATCK2)
+               {
+                       minfound = 0;
+                       for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+                       {
+                               if(!mine.minelayer_detonate)
+                               {
+                                       mine.minelayer_detonate = TRUE;
+                                       minfound = 1;
+                               }
+                       }
+                       if(minfound)
+                               sound (self, CHAN_WEAPON2, "weapons/mine_det.wav", VOL_BASE, ATTN_NORM);
+               }
+       }
+       else if (req == WR_PRECACHE)
+       {
+               precache_model ("models/flash.md3");
+               precache_model ("models/mine.md3");
+               precache_model ("models/weapons/g_minelayer.md3");
+               precache_model ("models/weapons/v_minelayer.md3");
+               precache_model ("models/weapons/h_minelayer.iqm");
+               precache_sound ("weapons/mine_det.wav");
+               precache_sound ("weapons/mine_fire.wav");
+               precache_sound ("weapons/mine_stick.wav");
+               precache_sound ("weapons/mine_trigger.wav");
+       }
+       else if (req == WR_SETUP)
+       {
+               weapon_setup(WEP_MINE_LAYER);
+       }
+       else if (req == WR_CHECKAMMO1)
+       {
+               // don't switch while placing a mine
+               if ((ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER)
+                       && self.ammo_rockets < cvar("g_balance_minelayer_ammo"))
+                       return FALSE;
+       }
+       else if (req == WR_CHECKAMMO2)
+               return FALSE;
+       return TRUE;
+};
+#endif
+#ifdef CSQC
+float w_minelayer(float req)
+{
+       if(req == WR_IMPACTEFFECT)
+       {
+               vector org2;
+               org2 = w_org + w_backoff * 12;
+               pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
+               if(!w_issilent)
+                       sound(self, CHAN_PROJECTILE, "weapons/mine_exp.wav", VOL_BASE, ATTN_NORM);
+       }
+       else if(req == WR_PRECACHE)
+       {
+               precache_sound("weapons/mine_exp.wav");
+       }
+       else if (req == WR_SUICIDEMESSAGE)
+               w_deathtypestring = "%s exploded";
+       else if (req == WR_KILLMESSAGE)
+       {
+               if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation)
+                       w_deathtypestring = "%s got too close to %s's mine";
+               else if(w_deathtype & HITTYPE_SPLASH)
+                       w_deathtypestring = "%s almost dodged %s's mine";
+               else
+                       w_deathtypestring = "%s stepped on %s's mine";
+       }
+       return TRUE;
+}
+#endif
+#endif
diff --git a/sound/weapons/mine_det.ogg b/sound/weapons/mine_det.ogg
new file mode 100644 (file)
index 0000000..3dd5e12
Binary files /dev/null and b/sound/weapons/mine_det.ogg differ
diff --git a/sound/weapons/mine_exp.ogg b/sound/weapons/mine_exp.ogg
new file mode 100644 (file)
index 0000000..664c444
Binary files /dev/null and b/sound/weapons/mine_exp.ogg differ
diff --git a/sound/weapons/mine_fire.ogg b/sound/weapons/mine_fire.ogg
new file mode 100644 (file)
index 0000000..a6408b3
Binary files /dev/null and b/sound/weapons/mine_fire.ogg differ
diff --git a/sound/weapons/mine_stick.wav b/sound/weapons/mine_stick.wav
new file mode 100644 (file)
index 0000000..ae2cb49
Binary files /dev/null and b/sound/weapons/mine_stick.wav differ
diff --git a/sound/weapons/mine_trigger.wav b/sound/weapons/mine_trigger.wav
new file mode 100644 (file)
index 0000000..539a84d
Binary files /dev/null and b/sound/weapons/mine_trigger.wav differ