PTR Changelog 2019-09-20: NPC Strongholds


  • Dev Team

    This post describes changes on the Public Test Realm.

    NPC Strongholds

    NPC Invaders now finally have a home!

    0_1568992144321_2019-09-20_342.png 0_1568981790490_invader-core-expand.gif

    We've deployed NPC Strongholds mechanic to the PTR for testing. Strongholds are spawned in all sectors on all shards. See the previous discussion to get more understanding of it. There are subtle differences from described there:

    • Invader Cores do not return damage on attack.

    • Invader Cores of all levels always have 1,000,000 hits.

    • There are two new "natural" (non-power) effects in Structure.effects:

      • EFFECT_INVULNERABLE means the structure is temporarily immune to attacks (Invader Core uses this effect while it's deploying the stronghold in the first stage);
      • EFFECT_COLLAPSE_TIMER will remove the structure when the timer is over. Invader Core will be respawned almost instantly
    • The most valuable loot is stored inside an Invader Core and only visible when it's destroyed.

    Keep in mind that defenders' logic is still under development, it will be much stronger after release. Also, all loot resources are placed with 1 unit amount, the formula is under development.

    Ruins

    We also introduced a new concept of ruins which is similar to tombstones. When you destroy a structure, it does not disappear but drops a ruin object. All resources are moved to the ruin's store. Basic player structures ruins have 500 ticks of decay, but some special cases exist:

    • InvaderCore ruins will last exactly the same time as the remaining EFFECT_COLLAPSE_TIMER on it.

    • When a user respawns, all structures are converted to ruins with 500,000 decay time.

    • When a novice player initially spawn into the room with another player's structures, all structures are converted to ruins with 100,000 decay time.

    This is how a room of a destroyed or respawned player may look like:

    0_1568982186654_2019-09-20_337.png

    API Changes


    This update is deployed to ptr private server branch (version 4.0.0-beta.6) on both npm and Steam:

    npm install screeps@ptr
    

    There are two new CLI commands to make testing strongholds easier:

    > help(strongholds);
    Available methods:
     - strongholds.spawn(roomName, [opts]) - Create a new NPC Stronghold, and spawn it to the specified room. 'opts' is an object with the following optional properties:
        * templateName - the name of stronghold template to spawn, default is random
        * x - the X position of the spawn in the room, default is random
        * y - the Y position of the spawn in the room, default is random
        * user - id of user which stronghold structures should belong to, default is "2" (Invader)
        * deployTime - delay in ticks until the stronghold is deployed
     - strongholds.expand(roomName) - Force an NPC Stronghold to spawn a new lesser Invader Core in a nearby room.
    Stronghold templates:
     - bunker1 [Level 1 bunker-style Stronghold]
     - bunker2 [Level 2 bunker-style Stronghold]
     - bunker3 [Level 3 bunker-style Stronghold]
     - bunker4 [Level 4 bunker-style Stronghold]
     - bunker5 [Level 5 bunker-style Stronghold]
    
    👍


  • Ruins are fun. Not sure it'll change gameplay much, probably less than tombstones.

    Resources in strongholds seem to be bugged:

    0_1568982982234_Capture.PNG

    I guess it should be more than one unit?


  • Dev Team

    @tigga All loot resources are placed with 1 unit amount, the exact formula is still under development.



  • @Taki asked on slack about nukes. It seems that you could just drop a nuke on the core, destroy the whole stronghold and loot the ruins. The ramparts have a max hits so it seems they can't be reinforced, and ruins seems to mean you don't have to worry about exploding the containers. I guess there's a mechanic that isn't obvious preventing this? Do ruins spawn from nuke hits?


  • Dev Team

    @tigga level 5 strongholds are able to expand max hits around the expected nuke impact area and spawn a boosted fortifier to raise ramparts. As for a nuke, it won't leave ruins or dropped resources. So yeah, you definitely can destroy a stronghold with a nuke, but its treasury will be destroyed as well.



  • How much details will we get in the client/websocket about a ruin? Will we know what kind of ruin it is, e.g. was it a wall, was it a tower? It would be interesting in the 3D client to render a different kind of ruin based on what the ruin is a ruin of 🙂

    I can see Ruin details a lot, I hope we recieve it all in the websocket 😄


  • Dev Team

    @thmsn it has the structureType property similar to construction sites.

    👍

  • YP

    Looking forward to test it on my private server 🙂



  • Example for tombstones taken from the docs:

    room.find(FIND_TOMBSTONES).forEach(tombstone => {
        if(tombstone.creep.my) {
            console.log(`My creep died with ID=${tombstone.creep.id} ` +
                 `and role=${Memory.creeps[tombstone.creep.name].role}`);
        }
    });
    

    How I think ruins should look like, for consistency and to make it easier to detect what was destroyed (for rebuilding or clearing relevant cached values):

    room.find(FIND_RUINS).forEach(ruin => {
        if(ruin.structure.my) {
            console.log(`My ${ruin.structure.structureType} with ID=${ruin.structure.id} was destroyed`);
        }
    });
    


  • Are ruins walkable? Or does it depend on what they are a ruin of? Do roads make ruins? Edit: I may jump on PTR and have a play next week



  • I like the ruins concept. I already liked the strongholds, so this is all win.

    Question: If I destroy a structure to create a ruin with a 500 tick timeout, can I use that to essentially bypass the "can't withdraw from a nuker" constraint? With proper placement, it should be possible to yoink the up to 400K energy from the Nuker's ruins to the storage in times of dire need.



  • I see in the docs that ruins are walkable. What about building on top of them? Is it allowed or not?



  • Reading the docs:

    An Invader Core has two lifetime stages: deploy stage and active stage. When it appears in a random room in the sector, it has ticksToDeploy property, public ramparts around it, and doesn't perform any actions. While in this stage it's invulnerable to attacks (has EFFECT_INVULNERABILITY enabled). When the ticksToDeploy timer is over, it spawns structures around it and starts spawning creeps, becomes vulnerable, and receives EFFECT_COLLAPSE_TIMER which will remove the stronghold when this timer is over.

    What is to stop me from placing 50xT3 boosted dismantle creeps on the public raparts and as soon as the core becomes open, just chewing it down very quickly? The stronghold ramparts will protect me, and my damage/tick is huge.

    Also, how do the structures handle a creep being where they want to spawn?

    I'm not sure I understand why we need this two-phase deployment.



  • I would also feel more comfortable if the "main" stronghold in a sector was owned by Invaders, rather than just being reserved. Feels more consistent. I'm currently going through code adding checks against the reservation username and fixing things where I use stuff like CONTROLLER_STRUCTURES[STRUCTURE_TOWER][room.controller.level]

    👍


  • https://screeps.com/ptr/#!/room/shard2/W19S15 There is a stronghold in this room but it isn't reserved. Is this intended?



  • I knocked up some code and thought about testing it on PTR, but for whatever reason my CPU usage is very high on PTR, and 10 second ticks doesn't really suit debugging that well. No shard specific code or anything and the same code is running fine on MMO.

    I guess I'll wait until they're on private servers.

    EDIT: Oh. Now it's fast. Thanks!



  • I got the following error:

    TypeError: Cannot read property 'energy' of null
        at exports.make.register.wrapFn.Object.defineProperties.C.RESOURCES_ALL.reduce (:41357:40)
        at Array.reduce ()
        at new  (:41355:29)
        at Object._storeGetter [as store] (:41284:12)
        at Object.get [as store] (eval at exports.defineGameObjectProperties (:1093:9), :7:61)
    

    When doing:

    for (let ruin of room.find(FIND_RUINS)) {
    	loot += _.sum(ruin.store)
    }
    

    Specifically, _.sum(ruin.store) seems to be failing. Not sure which room or ruin, just saw it in some logs.

    EDIT: Could be I'm getting the store of a ruined object that didn't have a store property - like a wall? Probably my fault and I was just confused by the error.

    EDIT2: Ok, the issue shows just seeing if there is a store property on a ruin: if (ruin.store) {

    W9S39 [ruin (extractor) #5d84b9f57c29e164bd6fcf85]
    [16:01:53][shard2]TypeError: Cannot read property 'energy' of null
        at exports.make.register.wrapFn.Object.defineProperties.C.RESOURCES_ALL.reduce (:41357:40)
        at Array.reduce ()
        at new  (:41355:29)
        at Object._storeGetter [as store] (:41284:12)
        at Object.get [as store] (eval at exports.defineGameObjectProperties (:1093:9), :7:61)
    

  • Dev Team

    We've migrated the Public Test Realm to our new cluster based on Intel Core i9-9900K and Nodejs 10, so you can test NPC Strongholds with a bit higher performance.



  • Something funky going on with caravans on PTR.

    https://screeps.com/ptr/#!/room/shard2/W0S20 tick 19029510

    Caravan creeps with no owner that aren't visible (but are clickable) on the room view, but are visible on the map view.


  • Dev Team

    This post is deleted!