The Spatials V3 devblog 2015-09-21

Internal development notes, very slightly cleaned up and commented a week later.

The focus for the past week was to start the work on the in-station logistics system.

- need now text display plus scrolling, v2 gui parity
    void iconText(std::string iconFrame, std::string iconColor, std::string text, std::string textColor)
    void animateScreenMoveBy(cocos2d::CCNode* node, float d, float x, float y)
    void animateFadeOut(cocos2d::CCNode* node, float d)

V2 often made use of scrolling text over the map when something interesting happened. This has been implemented now in V3, as an Scheme ECS system. It's also a good example on how to do a simple, custom display system.

- job for dismantling objects
    component, system
    red tintc
    finally need a "ready" flag component on objects
        added by successful construction
        removed when flagged for dismantling
    patch erase tool to:
        when ready, inject component
        when not ready, just destroy

The object dismantling tool was still running in editor mode. It has been replaced with a proper enitity job plus its system.

- logistics phase 1: basic items
    ItemComponent
        kind: Resource*
        amount
    display system for must(ItemC,PosC)+exclude(ChildC)
    maker: ItemMake (with auto scheme binding style)

This commit introduced logistics to V3. For starters a new ItemComponent was introduced, which represents a Resource kind plus a stack size.

- item index component: have a custom kind depending on its resource
    purely a flag to speed up item finding, has no data
    precalc kind (hashed internal resource name) into Resource

In order to fully leverage the ECS system entities which desire to represent a Resource kind can be directly indexed with the hash of the internal name of the resource. This will make it much faster to lookup item stacks in the world.

- Entity* TileMapSystem::closestEntityWithValidPath(float x, float y, AspectInst* ai)
- use closestEntityWithValidPath in WorkerSystem, do not pick jobs with an invalid path

Some logic was using a fast approach to finding nearby stuff, without taking into account the pathfinding. A new helper has been introduced to look up entities with a valid path from a given position.

- logistics phase 2: JobC/JobsSys also handles gathering of resources, optionally
    JobC also has logistics reqs (requiredResource, requiredAmount)
    JobsSys is now a little state machine
        current state idx is kept inside WorkerC, and reset on acquiring a new job
    JobsSys state -1: if logistics reqs go state 0, else go state 1
    JobsSys state 0
        if worker not pathing, find a parent-less ItemC ent comatible with res/amnt, then path to it
            if cannot find, drop the BusyC of job ent and worker ent, this is not job/worker for them
        on every JobsSys tick check if we can pick the required resources from the 9-neigh of the worker
            once picked, make it a child of the worker and go state 1
    JobsSys state 1
        same logic as existing (path to job position, action pose for N ticks)
- if req amount is for example 10, and there's 2 stacks of 8 and 4, JobsSys cannot send the officer to pick both of them
    re-run state 0 while the held amount by the worker is less than the required
    abort job when impossible to find more
- current logic is hardcoded to an amount of 1, including the item finder, which never checks amount, only kind
    -> after the previous fix this is not a problem anymore

The big one for the past week. The first phase of logistics just introduced the existence of item stacks. Phase 2 also made it optional for jobs to require a certain amount of resources. JobsSystem was enhanced to introduce a seek-and-pick behavior for worker entities, which now will find and approach nearby available stacks of items, picking and stacking items, until they meed the required amount, then go and perform their job. The tracking behaviour for picked stacks is just adding ChildComponent with trackPosition = true. The choice of generic components/systems for modelling relationships between entities (ChildComponent, BusyComponent) is proving to be very successful.

- helper: Entity* ItemHeldBy(World* world, Entity* worker, Resource* resource);
- helper: Entity* ItemDepositIn(World* world, Entity* worker, Entity* picked);
- helper: Entity* ItemPick(World* world, Entity* stack, int amount);
- helper: Entity* ItemPickHeldBy(World* world, Entity* worker, Resource* resource, int amount);

A series of C++ but Scheme-callable helpers related to items and item stacks were implemented. Rather than hardcoding item stacking logic into JobsSystem, all the code related to stacks has been implemented as stand alone functions that assume almost nothing about the involved entities. This will make it possible for any interested system to participate in logistics and item management.

- item consumption after a succesful job with logistics
    don't do in JobsSys, do inside the respective systems?
        general gathering does not require consumption for example
    example system (using objbuild.scm for now) is destroying held amount

A choice was made to not implement any resource consuption logic in JobsSystem. Just as a previous choice was made to not implement any logic for completed jobs, it will be the responsability of the system that spawned the job to apply any required logic over the picked resources, if any.

- system that detects item ents attached to idle workers and drops them on floor

It's possible to get a worker interrupted while they are in the middle of a job in a way that makes it impossible to resume it (deleting the job's object, for example). When this happens the worker can be left idling, but still holding an item stack. A very simple system was implemented to detect those workers and make them drop the stack on he ground, which will make lose its ChildComppment and make it available for picking again. The system was implemented in Scheme and its logic is just four lines of code:

(define-mod-export autodrop-component (bridge-hash "autodrop-component"))

(define-mod-export (station-autodrop-system-post-process s e)
    ([  held (ItemHeldBy (s #@world) e (persisting-null)) ]
        (unless (persisting-null? held)
            (ecs-remove-component held ChildComponent_Kind))))

(define-mod-export (make-station-autodrop-system body world)
    (ecs-make-system
        name: "station-autodrop-system"
        world: world
        aspect: (ecs-aspect
            must: (list PositionComponent_Kind autodrop-component)
            exclude: (list BusyComponent_Kind))
        phase: 30
        hooks: (list 'station-autodrop-system-post-process)))

All the entities that desire to be tracked by this system just need to add an autodrop-component.

- use nonlinear zoom in mouse wheel under windows

Finally :)

links

social