Unlock menu after failed join; remove contact damage; cover clean disconnects
ci / verify (push) Successful in 45s
ci / verify (push) Successful in 45s
A failed connection left the connect buttons disabled forever. _show_menu() returned early when a menu already existed, so the set_busy(false) that re-enables them never ran on the way back from _abort_connect -- the player was locked out of both joining and hosting with no way out but a restart. Also guards against a second attempt stacking on an in-flight one. Contact damage is gone as a concept: nothing in this game hurts you by touching it, because every threat should be a bullet you can see and dodge. The Stalker walked at you and dealt contact damage and nothing else, so it now carries a point-blank shotgun instead -- five pellets, 62 degrees, 18-tick lifetime for about 78px of reach, so it still has to close and leaves nothing lingering. tests/unit/test_content.gd asserts every hostile enemy has an emitter, so a new enemy cannot quietly reintroduce the mechanic. The menu's "Disconnect" DOES get the anti-cheese protection -- verified, not assumed. It calls Net.shutdown(), the socket closes, and the server takes the same linkdead path as a SIGKILL, because the channel is keyed on the socket closing rather than on how it closed. Made permanent: a --leave-after bot flag and two smoke assertions covering the polite exit alongside the hard kill, so a future "clean leave" message that skipped the channel would fail a test. The menu now says so out loud in a dungeon -- the mechanic only reads as fair if the cost is known before clicking. 103 tests, 12 smoke assertions; check.sh, test.sh and smoke.sh all pass.
This commit is contained in:
+24
-5
@@ -41,7 +41,6 @@ static func drifter() -> EnemyDef:
|
||||
d.display_name = "Drifter"
|
||||
d.max_hp = 40
|
||||
d.radius = 14.0
|
||||
d.contact_damage = 8
|
||||
d.move = EnemyDef.Move.DRIFT
|
||||
d.speed = 55.0
|
||||
d.visual = 0
|
||||
@@ -68,7 +67,6 @@ static func turret() -> EnemyDef:
|
||||
d.display_name = "Turret"
|
||||
d.max_hp = 70
|
||||
d.radius = 16.0
|
||||
d.contact_damage = 0
|
||||
d.move = EnemyDef.Move.STATIC
|
||||
d.speed = 0.0
|
||||
d.visual = 1
|
||||
@@ -88,18 +86,40 @@ static func turret() -> EnemyDef:
|
||||
return d
|
||||
|
||||
|
||||
## Walks at you and does nothing else. The pressure enemy.
|
||||
## Walks at you and fires a point-blank burst. The pressure enemy.
|
||||
##
|
||||
## It used to deal contact damage and nothing else. Nothing in this game hurts
|
||||
## you by touching you -- every threat is a bullet you can see coming and dodge,
|
||||
## which is the whole contract of the genre. So the Stalker's melee is a
|
||||
## shotgun with a deliberately tiny lifetime: ~78px of travel, which only
|
||||
## threatens once it has closed the distance, and leaves nothing lingering in
|
||||
## the arena afterwards.
|
||||
static func stalker() -> EnemyDef:
|
||||
var d := EnemyDef.new()
|
||||
d.id = ENEMY_STALKER
|
||||
d.display_name = "Stalker"
|
||||
d.max_hp = 30
|
||||
d.radius = 12.0
|
||||
d.contact_damage = 16
|
||||
d.move = EnemyDef.Move.APPROACH
|
||||
d.speed = 95.0
|
||||
d.retarget_interval = 20
|
||||
d.visual = 2
|
||||
d.pattern_loop_ticks = 45
|
||||
|
||||
var lunge := AimedSpreadEmitter.new()
|
||||
lunge.start_tick = 0
|
||||
lunge.interval = 45
|
||||
lunge.count = 5
|
||||
lunge.spread_deg = 62.0
|
||||
lunge.speed = 260.0
|
||||
lunge.radius = 6.0
|
||||
lunge.damage = 14
|
||||
# 18 ticks at 260 u/s is about 78px of reach -- shorter than the muzzle-to-
|
||||
# player distance at any range you would call "not point blank".
|
||||
lunge.lifetime = 18
|
||||
lunge.muzzle_offset = 10.0
|
||||
lunge.kind = SimConfig.KIND_HEAVY
|
||||
d.emitters = [lunge]
|
||||
return d
|
||||
|
||||
|
||||
@@ -110,7 +130,6 @@ static func dummy() -> EnemyDef:
|
||||
d.display_name = "Target Dummy"
|
||||
d.max_hp = 100000
|
||||
d.radius = 20.0
|
||||
d.contact_damage = 0
|
||||
d.move = EnemyDef.Move.STATIC
|
||||
d.visual = 3
|
||||
return d
|
||||
|
||||
Reference in New Issue
Block a user