Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit feature requirements #70

Open
2 of 54 tasks
artism90 opened this issue Sep 15, 2020 · 7 comments
Open
2 of 54 tasks

Unit feature requirements #70

artism90 opened this issue Sep 15, 2020 · 7 comments
Labels
tracker Tracks progress or other issues units Relating to ships or other movable units

Comments

@artism90
Copy link
Contributor

artism90 commented Sep 15, 2020

Requirements for each unit type to reach feature completeness. Each check box can be seen as a single task. Some tasks are compounds of a more comprehensive logic and may depend on each other. The descriptions contain pseudo code to give an idea on possibly relevant data to be implemented code-wise.

If a task involves interaction with another unit, the kind or subset of units is explicitly specified in there. In case it is not obvious, see the definition part below.

Balancing aspects like explicit values for ranges etc. are deliberately omitted to keep focus on the actual mechanics.

Definition:

  • Unit: Any moveable unit
  • Land unit: Any unit on land
  • Land troop: Military land unit
  • Ship: Any amphibic unit

Feel free to share your thoughts and add suggestions or point out edge cases to be taken into account.

Unit behavior to be implemented

General behavior for all units

  • Move in a route within an A* grid.
  • Mark/Unmark occupied_tiles = prevent units overlapping with each other.
  • Push forcefully idling units away if path blocking (especially relevant when trying to reach a warehouse in a tight spot).
  • Always push own and non-hostile units.
  • Never push hostile units.

Player-controlled land units

Land merchant

  • Destroy itself if health == 0.

User actions

  • Moving as a single unit: Just move to the destination point.
  • Trade/Exchange: Trade or exchange cargo with a non-hostile warehouse_in_range.
  • Trade route: to be determined

Melee unit

  • work in progress, to be determined

Ranged unit

  • work in progress, to be determined

Player-controlled ships

Huker (transport ship)

  • Moving as a single unit: Just move to the destination point.
  • Moving as a group of units: Take an appropriate group formation.
  • Switch the group formation accordingly to the user choice.
  • Have a stance of defensive | offensive. Defensive = Hold position when attacked. Offensive = Chase opponent to a certain extent and return to original position.
  • Destroy itself if health == 0.

User actions

  • Trade/Exchange: Trade or exchange cargo with a non-hostile warehouse_in_range.
  • Trade route: to be determined
  • Attack action: Stand and shoot after each cooldown timeout when hostile_target.is_in_range(), make the target (Ship | LandUnit | Building) take damage.
  • Escort/Follow action: Protect the selected unit, attack anyone who attacks it. If several units are escorting, make it take a reasonable group formation around it.
  • Move by waypoints: Avoid dangers by going a specifically defined route.
  • Patrol action: Put two or more waypoints to visit repeatedly.
  • Sell ship: Sell ship for a fixed price.
  • Self-destruction: Destroy unit.

Frigate (military ship)

Currently identical to Huker. The main differences lie in the values for storage_slots / storage_capacity and amount_of_cannons, which are not discussed here.

  • Moving as a single unit: Just move to the destination point.
  • Moving as a group of units: Take an appropriate group formation.
  • Switch the group formation accordingly to the user choice.
  • Have a stance of defensive | offensive. Defensive = Hold position when attacked. Offensive = Chase opponent to a certain extent and return to original position.
  • Destroy itself if health == 0.

User actions

  • Trade/Exchange: Trade or exchange cargo with a non-hostile warehouse_in_range.
  • Trade route: to be determined
  • Attack action: Stand and shoot after each cooldown timeout when hostile_target.is_in_range(), make the target (Ship | LandUnit | Building) take damage.
  • Escort/Follow action: Protect the selected unit, attack anyone who attacks it. If several units are escorting, make it take a reasonable group formation around it.
  • Move by waypoints: Avoid dangers by going a specifically defined route.
  • Patrol action: Put two or more waypoints to visit repeatedly.
  • Sell ship: Sell ship for a fixed price.
  • Self-destruction: Destroy unit.

Player NPC ships

Fisher

  • Move within a certain circular area to a random water tile after required_steps and start fishing, increase resource +1 per interval timeout until max of storage_capacity has reached.
  • Don't sail off if hostile_unit.is_in_range().
  • If being in sea already, cancel fishing and return home with current_storage so far.
  • Send feedback to its owner (fisher building) regarding the reason of return (storage_full, in_danger, ...).
  • If the owner (fisher building) gets destroyed, destroy itself as well.

Neutral NPC ships

Free Trader

  • Appear for the first time at a random edge of the map border once a warehouse exists.
  • Create a linked list of available trade_posts from the closest to farthest warehouse and start a new trading journey to sail for those harbours until everyone has been visited and the journey ends. New warehouses built in the midst of a running session will be added in the next run.
  • Navigate to the next warehouse in trade_posts.
  • Process trade transactions.
  • If trade_posts contains another element, rinse and repeat.
  • Leave the map at the closest map edge.
  • After an interval of "being abroad", return to the map at a random edge tile and create a new trading journey as described above.

Hostile NPC ships

Pirate

  • Has a relationship of hostile | neutral, ranging from 0.0 - 2.0.
    • 0 - 1 hostile - attack if hostile_unit.is_in_range()
    • 1 - 2 neutral - don't initiate attack
  • Can be bribed to reduce relationship to rivalising faction, with a random chance for the affected faction to find out about the briber and damage their mutual relationship.
  • Regularly patrol over waypoints, randomly created within a subset of the entire GridMap. The subset consists of all GridMap tiles with an appropriate distance to civilized area (settled islands and player territory in general). That said, the more the player expands, the farther the pirate has to retreat to stay in "calm waters".
  • Irregularly patrol over specific hotspots. Those spots are determined based on where general ship movement has been most frequent recently. Each tile on the map has a weight_of_interest which becomes "hotter" the more often it is passed by a ship and "cools down" the longer any activity is absent.
  • If hostile_unit.is_in_range(), attack.
  • If falls below minimum_health_threshold, retreat.
  • Destroy itself if health == 0.
@artism90 artism90 added units Relating to ships or other movable units tracker Tracks progress or other issues labels Sep 15, 2020
@artism90 artism90 changed the title [TRACKER] Unit feature requirements Unit feature requirements Sep 12, 2021
@SeanKuehl
Copy link
Contributor

I'm noticing that several different types of units need the destroy themselves when health == 0, would it be possible to put the "destroy self when health == 0" code in the unit class or are there some units that this doesn't fit for?

@artism90
Copy link
Contributor Author

artism90 commented Nov 4, 2021

This behavior would apply to most units, so it's certainly okay to make it a general rule. The few exceptions could be still overridden in their own subclass.

On the other hand though it could be neat to assign the health property only to specific unit classes which can be attacked and then check on the existence of health to determine if it's attackable or not.

Both approaches seem fine to me.

@SeanKuehl
Copy link
Contributor

I have a fork where I added a health property to the unit class and also added a function to be used later to check and destroy the unit if it's health is reduced to zero when it takes damage. Would this be enough for a pull request?

@artism90
Copy link
Contributor Author

artism90 commented Nov 4, 2021

Make a pull request and I will look over it.

@SeanKuehl
Copy link
Contributor

I'm looking at implementing marking the occupied tiles, I'd just like to ask some questions. How would you like me to visually mark them? Could I look into some kind of modulate to make the tile temporarily lighter in color for example? Also, for some of the other requirements for the unit it seems like you would want me to store something about the unit occupying that cell so that it can be accessed and pushed later if another unit tried to gain access to that tile. I was just wondering if you had any thoughts about how you would want me to implement that.

@artism90
Copy link
Contributor Author

artism90 commented Nov 6, 2021

Modulate would be sufficient for now.

The how-to is still pretty much open, so you're free to provide a possible approach and I'll happily check it out to see where to go from there and identify potential drawbacks.

Speaking of the tiles, it would be useful to have a set of debugging tools set up for visualizing the gridmap with all cells and the current state on each of them and the path all ships are following when moving.

@SeanKuehl
Copy link
Contributor

SeanKuehl commented Nov 7, 2021

While I was testing some things out, I ran into some issues. I was trying to find a way to change a Mesh at a cell index but couldn't find one. I then tried out this code, but it seems that the water tiles aren't valid in the world_to_map()? This code is called whenever a unit's move_vector changes, and it does change tiles, but only tiles on land, not the tiles under the actual ship I'm moving around(the ship in the WorldTown map).

`
func highlight_cell(unitPosition: Vector3) -> void:

var gridCellAtUnitPosition = grid_map.world_to_map(unitPosition)
var cellIndex = grid_map.get_cell_item(gridCellAtUnitPosition.x, gridCellAtUnitPosition.y, gridCellAtUnitPosition.z)

grid_map.set_cell_item(gridCellAtUnitPosition.x, gridCellAtUnitPosition.y, gridCellAtUnitPosition.z, 0)
`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tracker Tracks progress or other issues units Relating to ships or other movable units
Projects
None yet
Development

No branches or pull requests

2 participants