这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@castilma
Copy link

I started a list of all base types that need to be implemented in the engine. Add your thoughts and make changes.

@castilma castilma changed the title Nyan types doc: Nyan types Oct 14, 2016
Gold(Resource)
Food
...
...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, they're defined by the base data pack (aka the original game conversion) :)

Copy link
Author

@castilma castilma Oct 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/SFTtech/nyan/blob/master/doc/nyan.md says: "Defined in the game engine"
Maybe I'll change that there.
edit: changed that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx

Copy link
Member

@TheJJ TheJJ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm really happy to see that somebody else actually understood how nyan works, good job :)

The only thing I can recommend you is to understand that nyan only provides data, never logic. All logic is implemented in the engine. Once you internalized this, nyan makes much more sense and you can offload everything to the engine.

Which is quite intuitive actually, because the implementation of whatever game logic must be done in the engine. Nyan is only the tool to manipulate the numbers (and filenames).

# WIP4: how do we reference Animations?
# animation : file # one picture that contains all frames or, if a directory,
# contains all frames. # WIP5: naming scheme?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The engine has to support animations, it therefore defines Animation and we have to instance VillagerWalking(Animation): image : ... and reference it here.

Copy link
Author

@castilma castilma Oct 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe Ability() should get a member `animation : Animation'.
CooldownAbility does not need an Animation, but since every actual Ability will need an Animation, CooldownAbility can stay abstract. Right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. For example, castles don't have an attack animation. And if training units/researching techs/attack stances etc. also become abilities, neither do they.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if for example buildings have an ability without animation, they could reference to their static picture. Maybe that's a dirty workaround. The only alternative I see is to include an AnimatedAbility class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say the animation is a mixin, mainly used in abilities like Walking(Ability, Animation). If that ability becomes active, we can check in the engine if the ability also inherited from Animation, then activate and display the data specified there. That way, we can add custom animations for nearly everything we want but do not enforce it and can fall back to the standard walk animation etc.

# Everything you can see in the game # (WIP: but not assets, which is basically everything you see. Maybe better:)
# Everything that has some 'Ability' inherits from this.
ability : set(Ability)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything that has a (possibly varying) location ingame. Probably has a hp : float member.
Can't tell yet if we should add buildings as units as well or introduce another parent object for that.

We also have to think about if we wanna have a MoveAbility or simply create a engine-defined MovingUnit. The result is of course the same and i'm not sure if movement shall be done by some member value (the ability set) or by another base object. For nyan itselt it doesn't matter, depends how we wanna design the engine.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything that has a position has a look. So add an Animation or Sprite member?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, yes. Each Unit needs its idle look.

Open nyan implementation questions:

1. How do we say in Nyan, that a Towncenter attack depends on how many people are inside the building?
2. What about the building 'Ability' to carry units? will this lead to recursive references?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

References can be recursive of course, they can point to each other. But the carry ability would also be implemented in the engine i think, in a way that if the unit has the CarryAbility, nyan doesn't know about what the unit actually carries, but nyan only tells us it can carry 20 weight units, and that one unit type elephant will consume 5 weight units. That means each unit must define its weight :).
The engine then checks for each unit to board if current_weight + weight_of_new_unit_to_board >= max_weight and decides by that if it can board.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have to tell somehow, what units can go inside: many units can garrison the castle, but not the towncenter.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can define types of units: infantry, cavalry, ships, siege. this could help with the allowed_targets member in attackability and with the upgrades from research.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly, the original game has those unit types available for us, we can represent it simply in the inheritance hierarchy. (Huskarl(Cavalry) e.g.)


Open nyan implementation questions:

1. How do we say in Nyan, that a Towncenter attack depends on how many people are inside the building?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The possibility of attacking buildings must also be implemented in the engine. Nyan provides the information n units (of size x?) can garrison in the building. Then those people can either regularly attack from there or the engine multiplies the attack damage for the building.


-> If the {Towncenter,Castle} has certain damage, contained units need to leave.

-> A relict in a Church leads to increasing gold.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The damage info is a combination of nyan and the engine. The building itself must define a collapse threshold (in percent maybe) which the engine respects to send units out.

The relic gold is purely implemented in the engine which provides a "ResourceGenerator" object, which the relic inherits (Relic(ResourceGenerator)) and adds to the set(resource_type) += {Gold} and rate = 10. Nyan is not aware of the game mechanics, this is always the job of the engine (that was by the way the key enlightment i finally had to get a sufficient nyan design).

Resource():
name : text
icon : file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jup, the resource is part of the engine and the data pack can then create arbitrary resources.

name : text
description : text
icon: text
Tech(Update, HUDElement):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be a very good idea. I've never really thought about the ui integration, but having another mixin for that may be the way.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we still need a way to keep all the elements in order and allow 'pages'.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say the order and paging is done by categories first and addition order. If mods remove elements the layout won't get fucked up and we can also easily add new elements. If we use numbers for positioning things will always conflict. Tough thing, but just storing it via orderedsets is the easiest way i think.


-> We need a unified way/member-name to add a new animation to an 'Ability'

-> animations are stored in one big picture (or allow one file per frame?). How do we tell where in the picture is which frame? How can you tell to mirror a frame?
Copy link
Member

@TheJJ TheJJ Oct 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the original game, the relic thing is actually a new unit: "monk with relic". This is kinda stupid because it assumes only monks can carry relics, which is fine in age2 but very unsuitable for us.

So we can prepare the combination of a Carryable and some Unit in the sense that the carryable has to define its size and position, and we can then render the carryable in front of the unit. We can even define workaround replacement graphics that way in the sense that if it's a "known combination", the combination image is used (aka the monk with relic animation). How we model this in nyan I cannot tell right now (and haven't thought about it yet, so very good catch here).

The image metainformation should still be done in the good old .docx files as they're currently describing where a subimage is in one image. Things like animation speed, looping etc is defined in nyan though.
The engine will provide a nyan object Sprite which has a file member and others like the speed, etc. When this sprite is then required to be shown (e.g. because a unit uses it as its image) the engine will handle everything else internally, like parsing the subtexture information from the .docx, drawing it etc.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I rename the Animation class to Sprite?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think animation is fine, we can extend it to a 3d model animation in a few years then hehehe.

-> We need a unified way/member-name to add a new animation to an 'Ability'

-> animations are stored in one big picture (or allow one file per frame?). How do we tell where in the picture is which frame? How can you tell to mirror a frame?
5. Of what type are the ingame objects, that don't move and give ressources? goldmine, fish, dead deer? How are deer and dead deer connected?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd name them ResourceSpot, also defined by the engine (as it has to support giving out resources at that point).
Deer is a Animal which is a Unit i guess (so you can kill it), and if it's dead, like with all units it has to reference its dead form (to have the animations etc). So there is a DeadDeer(Animal, ResourceSpot) with hp = 0 and a resource type and amount. The gathering itself, the amount decay etcetc is done in the engine, just the decay rate is specified by nyan again.

Copy link
Author

@castilma castilma Oct 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why DeadDeer needs to inherit from from Animal. It needs:

  1. A dying animation.
  2. A rotting animation. After RessourceSpot.amount dropped to zero, play this and hold the last frame for like a minute, then remove this Unit completely.

Between 0 and 1 we need to decide if we want to hold the last frame from 0 or the first from 1. To me it looks like they're the same in the original assets.

My idea: We could add dying : animation to Unit. This is played when our unit dies. After that, create the referenced Deadunit(Unit). If it is a RessourceSpot, wait until RessourceSpot.amount dropped to zero.
Then play deadunit.dying (or deadunit.idle), which is the rotting animation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, could also work. I think you're right that all units have a dying animation but many won't have one. also we somehow need to model that the living deer is not a resource spot.

Basically we have multiple possibilities to model this:

  • store everything relevant for the dead deer in the living one already, aka rotting_animation and resource_decay and resource_type etcetc, this is the "bad" approach i'd say
  • have a separate DeadDeer that inherits from (original deer, resource spot) and updates graphics etc. the original deer then references to that object as on_death_become : Unit = DeadDeer. this requires a forward declaration which will be allowed in the next revision of the nyan design.
  • use abilities to test if the deer can even die. that ability then performs the death animation, another ability performs the resource collection, another one the decay.

I think the best approach is having an ability "being hunted" because it's different if a villager or a tribok killed it for the collectible food. That ability is implemented to change the unit type to DeadDeer once it is killed. The ability is included in the Deer abilities set, and also requires a forward declaration. It's the most overkill but also most extensible and awesome approach i'd say.


Mod questions:

1. Adding new units/buildungs: There are only blue units in the original assets. How does the engine now, what part of a frame needs new color?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh. Tricky thing this. Basically in the original data there is a "magical color" which is then recolored. Our approach is to paint that magical color as blue with an alpha value of 254. The fragment shader checks if the alpha value is 254 at some point, then looks up the blue tone, then replaces it with the matching yellow or whatever tone, and draws it.

In the original game this was done in assembly, but we process it in opengl with the teamcolor shader.

@TheJJ TheJJ added improvement Enhancement of an existing component documentation Involves the project documentation labels Oct 14, 2016
@TheJJ
Copy link
Member

TheJJ commented Oct 16, 2016

Can you rename the file to engine_types.md please?

@castilma castilma changed the title doc: Nyan types [WIP] doc: Nyan types Oct 16, 2016
resource : Resource
amount : int # initial amount
droprate : float # in units per second.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is called "decay" in the original, which i think is better.

@TheJJ
Copy link
Member

TheJJ commented Oct 16, 2016

We don't wanna have a file name separated with spaces in the repo please :)

@timo-42
Copy link

timo-42 commented Oct 16, 2016

is it possible to model something like: if the building(or all of the same type) is destroyed where something was researched, than the tech is lost and must be researched again?

@TheJJ
Copy link
Member

TheJJ commented Oct 16, 2016

Yes, but nyan would (if ever) just store the boolean and more information to enable that feature. The revert of the patch (aka undoing the tech) would require inversing patches, which we would have to add to nyan indeed. But the main work for this feature must be done in the engine (namely the "what happends when this building is destroyed).

@TheJJ TheJJ added the area: nyan Involves our data description language/database label Oct 16, 2016
@timo-42
Copy link

timo-42 commented Oct 16, 2016

How will this Stuff be implemented in the Engine? In my opinion, this should be implemented as Triggers:

Trigger:
type: always, once
conditions = expression
actions = [ list of action]
expression: True|False|condition and|or|xor True|False|condition

condition:

  • unit x is killed (e.g. king)
  • all military building of player x destroyed
  • all reliquiens captured
  • unit of player x discovers area x
  • first blood
  • first player researched tech x
  • building x destroyed

action:

  • change unit attribute to x
  • remove tech x
  • research tech x
  • send message to player/team
  • add food/wood to player x
  • create unit x
  • kill unit x
  • victory for team x
  • create other trigger
  • only limited to your imagination

example: player klicks tech Y research

new trigger 1:
type: once
condition: building x destroyed
action: [remove tech research, delete trigger 2]

new trigger 2:
type: once
condition: research Y finished
action: [ delete trigger 1, update units]

@TheJJ
Copy link
Member

TheJJ commented Oct 17, 2016

For non-general behavior modifications the trigger approach is awesome and we should definitively add those for building scenarios and map interactions.

But if we're talking about the general behavior of the game ("researches get lost when building is destroyed") then we should not have to add a trigger for each building x as you wrote, but instead for all buildings that do research. Nevertheless, it has to be implemented in the engine, and what amount of configuration data is stored in nyan for that is up to us.

idleLook : animation
death : Unit # What is the dead form of this Unit?
# Proposal:
# dying : animation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as noted in the Deer-discussion above, not every unit has the ability to die. then we'd have to insert a placeholder or an empty value for dying, which we wanna avoid.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, remove dying and death, right?

Building(Unit): # WIP: make another parent Object for Building?
# WIP2: Some buildings consist of a static frame and an animation on top. How do we reference that?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably an AnimatedBuilding, also the building annexes like the towncenter need to be modeled out of parts.
They have an ordered set of sprites (which may be animated) so the draw order is fixed.

# 3. remove `renameMe':
# possibilities: 1. `metainfo' is a regular file: description of `animation' (syntax?)
# 2. replace `metainfo' by more fields that describe `animation' (ugly imo, but maybe the best way)
# 3. remove `metainfo':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can either keep the current docx format or add a new one to just contain the frame positions and ids. i wouln't store information about the texture itself in nyan, the implicit reference to filename.anim or something might be better. the current docx approach is very simple and works well, we should load it on demand though and not on launch.

Copy link
Contributor

@MaanooAk MaanooAk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is still active...

damage : float # rename to baseDamage ?
HealingAbility(Ability): #WIP
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably must be split. Healing, Repairing and Healing_inside_a_building must be separate because its have different logic behind it (eg. repair has cost).

Healing_inside_a_building could also be megred with Garison.

HealingAbility(Ability): #WIP
# Workers can repair buildings, ships and siege weapons. Buildings heal contained Units, Priests can heal moving units (including siege weapons?)
# WIP: priests and workers need an animation for this, buildings not.
# Should we write that as an attack with negative
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will always have the same sign, so better positive which can be stored in a unsigned int

maxUnitsize : int # maximum size of each unit. If we want this, every movable unit should have a size member declared by a base class.
collapsingRate : float # percentage of health at which no units can be contained any longer.
AttackAbility(Ability):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Friendly fire
  • Min range
  • Area of effect
  • Consider projectiles

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you mean with "consider projectiles" and "area of effect"?


4. How do we add new animations?

-> How would a mod add a new relict-like object that can be carried (the animation)? can we describe composition of frames? How is it done by the original game?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original game: Two different units: monk and monk with relic

Copy link
Member

@TheJJ TheJJ Sep 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd do it with the ability to carry things, and a relic is a Carryable (and ResourceProvider when garrisoned in the monastry). To solve the asset combination the thing to be carried could be able to provide a overall carrying graphic, so the monk-with-relic graphic is activated as soon as it is picked up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ResourceProvider when garrisoned in the monastry

@TheJJ Now that you mention it, I'd even go further than that and regard the relic as some kind of BonusItem or BonusProvider. While it's true that AoE2 see relics only as another source for gold income, AoM's relics also provide boni like cheaper unit creation cost, faster research time. RoN has something similar, where rare resources on the map provide a bonus to the player who places a merchant on it (and rare resources can be controlled by multiple people). I think modders would also get very creative with this construct.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how would BonusProvider look like?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be similar to a ResourceProvider, but instead of giving a Resource, it provides a Bonus to the player who controls the BonusProvider. Boni could give stats upgrades (like 5% faster unit creation), area of effect buffs (like the generals in RoN), constant flow of resources (e.g. relics and feitoria in AoE2) or give a new ability to a hero who equips the Mighty Staff of Midgets, for example. Boni could also be temporary, permanent or tied to an item/unit/building.

In nyan a Bonus would probably be utilized as a nyan patch. Similar to the Tech() patch. BonusProvider on the other hand would be like a ResourceSpot:

Item():
     name : text

Bonus():
     timeout : float
     updates : set(NyanPatch)

ResourceBonus(Bonus):
     resources : Resource
     rate : float

BonusProvider():
    condition : Condition
    is_temporary : bool
    boni : set(Bonus)

# Content
Relic(Item, BonusProvider):
     name = "relic"
     
     condition = garrisoned
     is_temporary = false
     boni = {RelicBonus}

RelicBonus(ResourceBonus):
     resource = {Gold}
     timeout = -1.0
     rate = 1.0

     GoldBoost<resource>():
         amount += 2.0

     patches = {GoldBoost}

Or something like that. I hope i got the nyan syntax right.

Tech(Update, HUDElement):
Unit(): # WIP
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Cost
  • Have limit (The max number of units of this type that a player can have at an instance)
  • Had limit (The max number of units of this type that a player can create)

name : text
patches : set(NyanPatch) # Add your mod's patches to this member.
Tech():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Cost

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what type should cost be?
orderedset(int) (what order?) or the unimplemented dict(Ressource, int) ?

@elnabo
Copy link
Contributor

elnabo commented Nov 16, 2017

Maybe Unit should have a population field.

AoE1 and the last AoE2 extensions have infantries with 0.5 population usage.

@heinezen
Copy link
Member

More in draft: https://pad.stusta.de/p/openage-mod-api

@TheJJ
Copy link
Member

TheJJ commented Nov 22, 2018

Superseeded and continued by #1021 :)

@TheJJ TheJJ closed this Nov 22, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: nyan Involves our data description language/database documentation Involves the project documentation improvement Enhancement of an existing component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants