Author Topic: Allowing the Day/Night cycle to affect unit behavior.  (Read 1290 times)

Zoythrus

  • Guest
Allowing the Day/Night cycle to affect unit behavior.
« on: 20 December 2012, 03:28:43 »
Feature to add: Allow the engine's Day/Night cycle to actively affect units.

Reason for addition: This would create a much greater sense of atmosphere during gameplay. One of the most prominent examples is the lessening of sight/attack range during night, making surprise attacks much more useful at night. Another example would be to force units to morph (werewolves, anyone?) to match the cycle.

Means of addition: This idea would best be implemented as an optional part of the unit stats, so that the modders could tweak the night stats to their liking. I'm not sure if I would prefer a "Night" segment for each skill and command, or if each unit should get its own "Night" block in its XML.

Now, here's the special part, I plan on coding this myself! It seems like a simple way to learn the feel of the code. Would anyone out there have any suggestions to help the process go smoother?

Cygal

  • Guest
Re: Allowing the Day/Night cycle to affect unit behavior.
« Reply #1 on: 20 December 2012, 09:02:18 »
Sounds like a good idea. It doesn't sound that easy though! I don't know the code, but here's a lot of subtasks I can think of:
  • define the XML structure (and yeah, should be optional)
  • update the C++ structures/classes so that they can receive the new info
  • modify the XML reading code to put the correct night info into C++
  • identify the part of the code where you'll know that night has come
  • identify the part of the code where you should update the units informations
  • make sure it works correctly in single player (maybe there's caching involved, or the sight change is going to cause a graphics bug
  • make sure it also works with multiplayer mode (no out of syncs)

I think you should start with 3, 4 and 5, starting with arbitrarily set modifications (eg. all units/(buildings?) get sight reduced by 2 when night comes). 1, 2, 3 are probably more boring and you should get to them only when the basic functionality works.

Hope that helps!

Omega

  • MegaGlest Team
  • Dragon
  • ********
  • Posts: 6,167
  • Professional bug writer
    • View Profile
    • Personal site
Re: Allowing the Day/Night cycle to affect unit behavior.
« Reply #2 on: 20 December 2012, 09:28:22 »
Possible syntax, then:

Child of <parameters>:
Code: [Select]
<alternative-night-stats value="true">
<max-hp value="0" />
<max-ep value="0" />
<sight value="0" />
<attack-strenght value="0" />
<attack-range value="0" />
<armor value="0" />
<move-speed value="0" />
<production-speed value="0" />
<morph value="true">
<morph-skill value="morph_skill" />
<morph-unit name="werewolf"/>
</morph>
</alternative-night-stats>

This code uses snippets from the upgrade code and morph command code, potentially allowing the least number of changes (for you). Perhaps the "attack-strenght" element could also be defined by the proper spelling (or maybe just with the proper spelling).  The parameters are all static values and accept negatives (so a sight value of -2 will reduce the sight by 2 at night). All tags should be optional and default to false/0, including the parent tag (<alternative-night-stats>) and morph tag (<morph>). The morph tag uses two key tags from the morph command (since we don't want there to be an actual command on the unit; we want the morphing to be automatic). It would tell us the morph skill to use (which would determine how fast the morphing is and the animation) and what we're morphing into (since that's normally done at the command level). The problem I see is that it might be possible to "skip" the morphing if you gave the unit a command during the animation. Optionally, you could try and code a way that the morphing cannot be skipped (other commands queue up after the morphing), but if that's too much, it should be fine with allowing it to skip.

And in addition to what Cygal said, don't forget to reset the stats when day comes around again. Also, consider what you're doing with minimum HP and EP. Are they going to increase/decrease based on the difference in the night stats? Or will they stay the same? I think the former works best, since the latter makes HP boosts useless unless the unit is quickly healed up. However, this also means the unit can be killed upon transformation if the form it morphs into has a difference in HP greater than the current HP. But I'm fine with that. Alternatively, it could never reduce the unit below 1 HP, allowing it to survive, but barely.

Good luck.
Edit the MegaGlest wiki: http://docs.megaglest.org/

My personal projects: http://github.com/KatrinaHoffert

MoLAoS

  • Ornithopter
  • *****
  • Posts: 433
    • View Profile
Re: Allowing the Day/Night cycle to affect unit behavior.
« Reply #3 on: 20 December 2012, 15:23:59 »
Hehe, in GAE we would just use an effect. Trololol.

Zoythrus

  • Guest
Re: Allowing the Day/Night cycle to affect unit behavior.
« Reply #4 on: 2 January 2013, 02:14:15 »
After being told by multiple sources that this idea might be harder than I had anticipated, I will be postponing work on this feature for something simpler (although my adv. C++ class was a few semesters ago, I just need a kickstart to get back "in the groove").

But, I would assume that the code would look something like this:
Code: [Select]
if(parametersNode->hasChild("nighttime-effects") == true){
if(TimeFlow::isNight()){
int oldStats[8]=(parametersNode->getChild("sight")->getIntValue(), parametersNode->getChild("max-hp")->getIntValue(), etc);

sight= parametersNode->getChild("sight")->getAttribute("value")->getIntValue();
        max-hp= parametersNode->getChild("max-hp")->getIntValue(),
        etc
}
elseif(TimeFlow::!isNight() && TimeFlow->!firstTime){
         sight = oldStats[0];
         max-hp = oldStats[1];
         etc
}
else{
something.....I haven't worked this part out yet.....
}

Maybe?

MoLAoS

  • Ornithopter
  • *****
  • Posts: 433
    • View Profile
Re: Allowing the Day/Night cycle to affect unit behavior.
« Reply #5 on: 2 January 2013, 03:22:52 »
I added this to Mandate a bit ago.

Edit: Okay that was a lie. But after I made this post I implemented it and it compiled first try and worked in game.

Basically every world tick:

for (int i = 0; i < getFactionCount(); ++i) {
    for (int j = 0; j < getFaction(i)->getUnitCount(); ++j) {
        Unit *unit = getFaction(i)->getUnit(j);
        if (isDay()) {
            unit->applyDayPower();
        } else if (isNight()) {
            unit->applyNightPower();
        }
    }
}

The apply functions just trigger computeTotalUpgrade after setting the unit's dayCycle variable to the proper time. Its easily expandable if you want to have more periods of the day like dawn or dusk or noon or midnight.

Then each unit has an optional enhancement for day and night, if you don't put it in the game sees the NULL value and doesn't do anything. Only takes like 40 lines of code :) Also I'm gonna mod it so that it only triggers on the time change cause doing it every tick is just a waste of CPU.
« Last Edit: 2 January 2013, 04:31:57 by MoLAoS »

Zoythrus

  • Guest
Re: Allowing the Day/Night cycle to affect unit behavior.
« Reply #6 on: 2 January 2013, 05:48:25 »
I assume that this all went in the unit.cpp, MoLAos? Actually, what is that file all about? I skimmed through it, then got rather confused....
Yes, I've coded large projects before, but nothing near the scale of Glest! It's why I'm finding difficult to keep it all straight.

Now, about your code specifically, where did the "getFactionCount()" and "getUnitCount()" come from? Or did you have to make those for this code?

MoLAoS

  • Ornithopter
  • *****
  • Posts: 433
    • View Profile
Re: Allowing the Day/Night cycle to affect unit behavior.
« Reply #7 on: 2 January 2013, 06:04:08 »
EDIT:
I checked into he MegaGlest source but its even more different than I had imagined. I can't really give an MGified version of my code.

that goes into World::tick() actually.

here is the actual code after I fiddled with it:

   for (int i = 0; i < getFactionCount(); ++i) {
      for (int j = 0; j < getFaction(i)->getUnitCount(); ++j) {
          Unit *unit = getFaction(i)->getUnit(j);
          if (timeFlow.isDay() && !unit->dayCycle) {
              unit->dayCycle = true;
              unit->computeTotalUpgrade();
          } else if (timeFlow.isNight() && unit->dayCycle) {
              unit->dayCycle = false;
              unit->computeTotalUpgrade();
          }
      }
   }

You need to add some stuff to unit_type and unit files though. Also it uses enhancements which MegaGlest doesn't have as far as I'm aware.

Also GAE and MG have different unit related file organization and different folder names and crap.
« Last Edit: 2 January 2013, 16:29:02 by MoLAoS »