unknown-horizons / godot-port

Unknown Horizons Godot Engine Port
https://www.unknown-horizons.org
GNU General Public License v2.0
665 stars 83 forks source link

Unit feature requirements #70

Open artism90 opened 4 years ago

artism90 commented 4 years ago

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:

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

Player-controlled land units

Land merchant

User actions

Melee unit

Ranged unit

Player-controlled ships

Huker (transport ship)

User actions

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.

User actions

Player NPC ships

Fisher

Neutral NPC ships

Free Trader

Hostile NPC ships

Pirate

SeanKuehl commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

Make a pull request and I will look over it.

SeanKuehl commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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)
`