Jump to content

Photo

Elemental Damage


  • Please log in to reply
77 replies to this topic

#31 grayswandir

grayswandir

    semi-genius

  • Members

Posted 21 August 2013 - 07:24 PM

Yeah, I generally agree that it's not the best symbol to use. I definitely prefer := or <-, or really anything that kind of indicates movement. The real reason = is used for assignment, I think, is because assignment generally happens a lot more than testing for equality, and programmers don't like typing any more than they have to. :rolleyes:


  • David likes this

#32 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 21 August 2013 - 07:25 PM

:lol:


  • David likes this

#33 David

David

    Fallen leaves... adorn my night.

  • Administrators
  • Real Name:David
  • Pronouns:He / Him

Posted 21 August 2013 - 07:32 PM

Yeah, I generally agree that it's not the best symbol to use. I definitely prefer := or <-, or really anything that kind of indicates movement. The real reason = is used for assignment, I think, is because assignment generally happens a lot more than testing for equality, and programmers don't like typing any more than they have to. :rolleyes:

Wow, laziness dominates the programming world! :D



#34 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 21 August 2013 - 07:45 PM

Ok, so I tried my hand at altering the code and I came up with this:

// The fake amount of hp.
const int ELEMENT_FIRE = 1;
const int ELEMENT_FOREST = 2;
const int ELEMENT_WATER = 3;
const int ELEMENT_WIND = 4;
const int ELEMENT_ICE = 5;
const int ELEMENT_EARTH = 6;
const int ELEMENT_LIGHT=7;
const int ELEMENT_SHADOW = 8;
const int ELEMENT_SPIRIT = 9;
 

// Misc slot for Link's hp last frame..
const int MISC_LINK_HP = 1;

// Link's base element
int Link_Element = 0;


int GetDamageMultiplier(int attackElement, int LinkElement) {
  if (attackElement == 0 && LinkElement == 0) {return 1;}
  else if (attackElement == ELEMENT_FIRE && LinkElement == ELEMENT_FIRE) {return 0.75;}
  else if (attackElement == ELEMENT_FOREST && LinkElement == ELEMENT_FOREST) {return 0.75;}
  else if (attackElement == ELEMENT_WATER && LinkElement == ELEMENT_WATER) {return 0.75;}
  else if (attackElement == ELEMENT_WIND && LinkElement == ELEMENT_WIND) {return 0.75;}
  else if (attackElement == ELEMENT_ICE && LinkElement == ELEMENT_ICE) {return 0.75;}
  else if (attackElement == ELEMENT_EARTH && LinkElement == ELEMENT_EARTH) {return 0.75;}
  else if (attackElement == ELEMENT_LIGHT && LinkElement == ELEMENT_LIGHT) {return 0.75;}
  else if (attackElement == ELEMENT_SHADOW && LinkElement == ELEMENT_SHADOW) {return 0.75;}
  else if (attackElement == ELEMENT_SPIRIT && LinkElement == ELEMENT_SPIRIT) {return 0.75;}
  else if (attackElement == ELEMENT_FIRE && LinkElement == ELEMENT_FOREST) {return 1.5;}
  else if (attackElement == ELEMENT_FOREST && LinkElement == ELEMENT_WATER) {return 1.5;}
  else if (attackElement == ELEMENT_WATER && LinkElement == ELEMENT_FIRE) {return 1.5;}
  else if (attackElement == ELEMENT_WIND && LinkElement == ELEMENT_ICE) {return 1.5;}
  else if (attackElement == ELEMENT_ICE && LinkElement == ELEMENT_EARTH) {return 1.5;}
  else if (attackElement == ELEMENT_EARTH && LinkElement == ELEMENT_WIND) {return 1.5;}
  else if (attackElement == ELEMENT_LIGHT && LinkElement == ELEMENT_SHADOW) {return 1.5;}
  else if (attackElement == ELEMENT_SHADOW && LinkElement == ELEMENT_SPIRIT) {return 1.5;}
  else if (attackElement == ELEMENT_SPIRIT && LinkElement == ELEMENT_LIGHT) {return 1.5;}

 
  // Finally, return 1 if for some reason we haven't found a multiplier yet.
  return 1;}
 
 
// Updates this npc.
void Link_Update() {
  Link_Damage();}
 

 
// Take damage as appropriate.
void Link_Damage() {
  // See if we took any hits, and quit if we didn't.
  int hit = Link->HP[MISC_LINK_HP] - Link->HP;
  if (hit <= 0) {return;}
  // Go back up to the hp we had before (so we can subtract the proper
  // amount this time.)
  Link->HP = Link->HP[MISC_LINK_HP];
  // Item editor only let's us specify damage in increments of 2,
  // so half the damage here where we interpret it.
  hit >>= 1;
  // Interpret the hit value.
  int element = hit % 10;
  int damage = (hit * 0.2) >> 0;
  // Damage multipliers
  damage *= GetDamageMultiplier(element, Link_Element);
  // Apply damage.
  Link->HP -= damage;
  // Update the 'old' value to the new amount.
  Link->HP[MISC_LINK_HP] = Link->HP;
}

item script ElementTunic
{
 void run(int TunicElement, int TunicDefense)
 {
  Link_Element = TunicElement; 
  damage /= TunicDefense;
  //Insert other tunic functions here
 }
}

Did I miss anything? (other than the line in my global to update Link's HP)


Edited by Lineas, 21 August 2013 - 07:47 PM.


#35 grayswandir

grayswandir

    semi-genius

  • Members

Posted 21 August 2013 - 08:08 PM

First of all, you don't need to copy anything that already exists. If you already have ELEMENT_FIRE defined elsewhere, you don't need to define it again (and it will in fact blow up at you for trying to). Same with GetDamageMultiplier - that didn't need to be modified at all. It was set up with attackElement and targetElement - those work just as well whether Link is on one end or the other.

 

Instead of Link->HP[MISC_LINK_HP], you should have made a global variable (Like LinkOldHP or something).

Link->HP is a single variable.

enemy->Misc[] is an array of 16 variables, enemy->Misc[0] through enemy->Misc[15].

Saying Link->HP[x] doesn't make sense, because Link->HP is a single variable, not an array.

 

In the item script, what is the damage /= TunicDefense line doing? There is no damage variable in that script, so you can't divide it.



#36 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 21 August 2013 - 08:19 PM

Well, I needed the damage multiplier to be different for Link than for monsters, because the return values are different, that's why I did that , and the constants were only in there for reference (I was going to remove them, and combine the damage multiplier function with the other one before I added this section to the other element script)

 

I changed all the Link->HP[MISC_LINK_HP] sections to just "MISC_LINK_HP", so that should fix that problem

 

and I couldn't figure out how to do the damage divisors for the item script, but I was trying to call to the "damage *= GetDamageMultiplier(element, Link_Element);"  line, then divide the result of that by the D1 argument (which obviously, I did wrong)

 

EDIT: Wait, what if I added "int DamageTotal = damage *= GetDamageMultiplier(element,Link_Element); "  Then changed the word "damage" to "DamageTotal"?


Edited by Lineas, 21 August 2013 - 08:29 PM.


#37 grayswandir

grayswandir

    semi-genius

  • Members

Posted 21 August 2013 - 08:35 PM

The problem is it's still has the "signature" GetDamageMultiplier(int, int), which is exactly the same as the monster's GetDamageMultiplier function. So the code won't know which one to use. You can either change its name (GetLinkDamageMultiplier(int, int)), or change the number of arguments (GetDamageMultiplier(int) - you don't need to pass Link's element in, you can just use it directly).

 

To do the damage divisor, you'd need to store it in a global variable, just like link's element:

Link_Element = 0;
Link_Defense = 1;
 
item script ElementTunic
{
  void run(int TunicElement, int TunicDefense)
  {
    Link_Element = TunicElement;
    Link_Defense = TunicDefense;
  }
}

Then you'd look up that value in the actual damage code:

// Damage multipliers
damage *= GetDamageMultiplier(element, Link_Element);
damage /= Link_Defense;


#38 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 21 August 2013 - 08:44 PM

Oooh, ok, I get it. I still don't understand why I can't combine the GetLinkDamageMultiplier code into the existing GetDamageMultiplier code... but then again, as I recall, I had to do a little messing around with the original code because it had gotten too long, so it's probably better to make it a separate function.



#39 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 21 August 2013 - 10:13 PM

So, it should look something like this, then:

// Misc slot for Link's hp last frame..
const int MISC_LINK_HP = 1;
int Link_Defense = 1
int Link_Element = 0


int GetLinkDamageMultiplier(int attackElement, int LinkElement) {
  if (attackElement == 0 && LinkElement == 0) {return 1;}
  else if (attackElement == ELEMENT_FIRE && LinkElement == ELEMENT_FIRE) {return 0.75;}
  else if (attackElement == ELEMENT_FOREST && LinkElement == ELEMENT_FOREST) {return 0.75;}
  else if (attackElement == ELEMENT_WATER && LinkElement == ELEMENT_WATER) {return 0.75;}
  else if (attackElement == ELEMENT_WIND && LinkElement == ELEMENT_WIND) {return 0.75;}
  else if (attackElement == ELEMENT_ICE && LinkElement == ELEMENT_ICE) {return 0.75;}
  else if (attackElement == ELEMENT_EARTH && LinkElement == ELEMENT_EARTH) {return 0.75;}
  else if (attackElement == ELEMENT_LIGHT && LinkElement == ELEMENT_LIGHT) {return 0.75;}
  else if (attackElement == ELEMENT_SHADOW && LinkElement == ELEMENT_SHADOW) {return 0.75;}
  else if (attackElement == ELEMENT_SPIRIT && LinkElement == ELEMENT_SPIRIT) {return 0.75;}
  else if (attackElement == ELEMENT_FIRE && LinkElement == ELEMENT_FOREST) {return 1.5;}
  else if (attackElement == ELEMENT_FOREST && LinkElement == ELEMENT_WATER) {return 1.5;}
  else if (attackElement == ELEMENT_WATER && LinkElement == ELEMENT_FIRE) {return 1.5;}
  else if (attackElement == ELEMENT_WIND && LinkElement == ELEMENT_ICE) {return 1.5;}
  else if (attackElement == ELEMENT_ICE && LinkElement == ELEMENT_EARTH) {return 1.5;}
  else if (attackElement == ELEMENT_EARTH && LinkElement == ELEMENT_WIND) {return 1.5;}
  else if (attackElement == ELEMENT_LIGHT && LinkElement == ELEMENT_SHADOW) {return 1.5;}
  else if (attackElement == ELEMENT_SHADOW && LinkElement == ELEMENT_SPIRIT) {return 1.5;}
  else if (attackElement == ELEMENT_SPIRIT && LinkElement == ELEMENT_LIGHT) {return 1.5;}

 
  // Finally, return 1 if for some reason we haven't found a multiplier yet.
  return 1;}
 
 
// Updates this npc.
void Link_Update() {
  Link_Damage();}
 

 
// Take damage as appropriate.
void Link_Damage() {
  // See if we took any hits, and quit if we didn't.
  int hit = MISC_LINK_HP - Link->HP;
  if (hit <= 0) {return;}
  // Go back up to the hp we had before (so we can subtract the proper
  // amount this time.)
  Link->HP = MISC_LINK_HP;
  // Item editor only let's us specify damage in increments of 2,
  // so half the damage here where we interpret it.
  hit >>= 1;
  // Interpret the hit value.
  int element = hit % 10;
  int damage = (hit * 0.2) >> 0;
  // Damage multipliers
  damage *= GetLinkDamageMultiplier(element, Link_Element);
  damage /= Link_Defense;
  // Apply damage.
  Link->HP -= damage;
  // Update the 'old' value to the new amount.
  MISC_LINK_HP = Link->HP;
}

item script ElementTunic
{
 void run(int TunicElement, int TunicDefense)
 {
  Link_Element = TunicElement; 
  Link_Defense = TunicDefense;
  //Insert other tunic functions here
 }
}

Yes?

 

EDIT: I just saw that you said I don't need to pass Link's element into the damage multiplier part, why is that? I did it anyways, since I wasn't sure how it would work, otherwise


Edited by Lineas, 21 August 2013 - 10:18 PM.


#40 grayswandir

grayswandir

    semi-genius

  • Members

Posted 21 August 2013 - 10:27 PM

You don't want MISC_LINK_HP to be a constant - it's a variable storing how much hp Link had last frame, so we can tell how much he got hit for this frame.

 

Since Link_Element is a global variable, you can see it inside of GetLinkDamageMultiplier. Since you know you're always going to pass in Link_Element as the second argument to GetLinkDamageMultiplier, you can skip passing it in and use it directly. So you can have this instead:

int GetLinkDamageMultiplier(int attackElement) {
  if (attackElement == 0 && Link_Element == 0) {return 1;}
  else if (attackElement == ELEMENT_FIRE && Link_Element == ELEMENT_FIRE) {return 0.75;}
  else if (attackElement == ELEMENT_FOREST && Link_Element == ELEMENT_FOREST) {return 0.75;}
  // ...


#41 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 21 August 2013 - 10:32 PM

OH! Ok, I get that.... But then why is the equivalent one for NPCs a constant, then (MISC_NPC_OLD_HP)?

 

EDIT: So, it should be


Edited by Lineas, 21 August 2013 - 10:34 PM.


#42 grayswandir

grayswandir

    semi-genius

  • Members

Posted 21 August 2013 - 10:56 PM

Almost. You didn't change LinkElement in GetLinkDamageMultiplier to Link_Element, the actual global variable.

 

 

Each enemy has an array of size 16 called Misc. This is a set of 16 variables meant for the scripter to store any information that they wanted to attach to a specific enemy. The original script appropriated one of those array slots for storing the enemy's hp from last frame. So MISC_NPC_OLD_HP was not a variable - it was a constant telling us which Misc slot we were using to store the old hp in.

 

For Link, we can just use a variable without worrying about the Misc array. We can get away with this because there's only ever 1 Link. There are many enemies, so we can't just create an EnemyOldHp variable.

 

(We could create an array - int EnemyOldHp[20], but that would limit us to 20 enemies on the screen (and break if there were more), and if an enemy died, say enemy 10, then all of a sudden enemy 11 would be the 10th enemy, and the ordering would be messed up. There's ways around this, of course, but by far the simplest way is to use the enemy->Misc[] array.)


Edited by grayswandir, 21 August 2013 - 10:56 PM.

  • Binx likes this

#43 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 21 August 2013 - 11:16 PM

Ok, this is the final version of Elemental.z (I think, hopefully I didn't miss anything stupid)

I hard-coded most of the element values, since all the tunics are going to have different bonuses, and I figured that would be easier than trying to code some kind of "tunic bonus ring", and also added a neutral tunic

 

That look about right?

 

EDIT: Oh, wait, the wind and earth tunics should use floats, huh, since I'll be needing to give them slightly different defense divisors that are going to use decimals, huh?


Edited by Lineas, 21 August 2013 - 11:27 PM.


#44 grayswandir

grayswandir

    semi-genius

  • Members

Posted 21 August 2013 - 11:33 PM

That looks like it will run.

 

Actually, I'm thinking it will be easier just to have 1 tunic script. This is because you also need to turn off all the other tunic bonuses whenever you get a new tunic (e.g. If you're not getting the wind or earth tunic, you need to reset Link's speed to 1).

 

There's two ways to do this:

void TurnOffTunicBonuses() {
  ExtraBombDropChance = 0;
  ExtraArrowDropChance = 0;
  // ...
  }
 
item script FireTunic {
  void run(int TunicDefense) {
    TurnOffTunicBonuses()
    Link_Element = ELEMENT_FIRE;
    Link_Defense = TunicDefense;
    ExtraBombDropChance = 0.2;}}
 
item script ForestTunic {
  void run(int TunicDefense) {
    TurnOffTunicBonuses();
    Link_Element = ELEMENT_FOREST;
    Link_Defense = TunicDefense;
    ExtraArrowDropChance = 0.4;}}
 
// ...

and

item script ElementalTunic {
  void run(int element, int defense) {
    Link_Element = element;
    Link_Defense = defense;
 
    if (element == ELEMENT_FIRE) {ExtraBombDropChance = 0.2;}
    else {ExtraBombDropChance = 0;}
 
    if (element == ELEMENT_FOREST) {ExtraArrowDropChance = 0.4;}
    else {ExtraArrowDropChance = 0;}
 
    // ....
    }}

Edit: ints and floats are, unfortunately, the exact same thing in ZScript, for which the proper term is a fixed point number. So even if you call a variable an int, it can still take decimals like a float. This is because ZScript changed the variables halfway through being created or something.


Edited by grayswandir, 21 August 2013 - 11:35 PM.


#45 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 21 August 2013 - 11:35 PM

Wouldn't it just be easier to just uncheck the "keep lower level items" box?




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users