Sturdy status

RCXDan

Champion of Brightmoon Tor
Veteran
Joined
Jan 4, 2019
Messages
170
Reaction score
311
First Language
English
Primarily Uses
RMVXA
No matter what I try, this is the Big Thing that always has me stumped: having the player retain 1 HP upon taking a lethal attack and not entering an HP zero state.

I know it's possible for enemies, but I haven't been able to crack it despite all my attempts. It usually ends up with the player in an Immortal state but with zero HP and not being able to do any actions.

Any help with this either through scripts or in-engine work would be very much appreciated.
 

Mhin Ra

Veteran
Veteran
Joined
Aug 17, 2015
Messages
61
Reaction score
18
First Language
English
Primarily Uses
RMVXA
I don't use the RPGMaker battle system in my game, so I am not super familiar. That said, I agree that there doesn't seem to be an obvious solution to this problem. I wrote a script that seems to more or less do what you want:

Ruby:
class Game_Battler
  attr_accessor :catLives
 
  alias :mrCatLives_addNewState :add_new_state
  def add_new_state(state_id)
    if state_id == death_state_id && @catLives != nil && @catLives > 0
      @catLives -= 1
      revive()
      return
    end
    mrCatLives_addNewState(state_id)
  end
end
If you then make a call like

Ruby:
$game_party.members[0].catLives = 2
It seems to cause the actor to survive two attacks at 1 HP. I am not quite sure if a script line like this is something you can use at the appropriate point in your battle; it might be possible to hook it up to some state or something... but again, I am super not familiar with the RPGMaker battle stuff.

There might also be a more elegant way to achieve this; one of the other scripters might have some ideas. The restrictions system seems like it might be appealing for this sort of thing, except that they seem to have encoded a bunch of behaviors by doing integer comparisons on the ids of the restrictions... which means extending it is a bit of a minefield.

Anyway, I hope this helps. Let me know if it does something weird b/c my testing was perforce quite limited.
 

RCXDan

Champion of Brightmoon Tor
Veteran
Joined
Jan 4, 2019
Messages
170
Reaction score
311
First Language
English
Primarily Uses
RMVXA
Holy hell it works. The only caveat is that it shows off the death message even when they don't die, but other than that this is pretty godlike.

The way I used it was by having a test battle where I activate it through a script call before the fight starts, but I can see this being activated in better ways down the line. Thank you so much, @Mhin Ra.
 

Mhin Ra

Veteran
Veteran
Joined
Aug 17, 2015
Messages
61
Reaction score
18
First Language
English
Primarily Uses
RMVXA
Yeah; you're totz right. I am not 100% sure yet why that message is showing up; I would have assumed it was b/c a state was being added, but I think I'm short circuiting that. I'll keep playing with it and see if I can figure out how to make the message not happen. However, this should at least let you prototype with the concept to see how it feels :)
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
2,604
Reaction score
1,946
First Language
English
Primarily Uses
RMMV
If you want it not to show the text, you also need to set the battler's result object's added_states array back to [] when you call revive() so that Window_BattleLog doesn't pick it up when it processes what text it needs to show.
 

RCXDan

Champion of Brightmoon Tor
Veteran
Joined
Jan 4, 2019
Messages
170
Reaction score
311
First Language
English
Primarily Uses
RMVXA
@Trihan Not sure how to do that, unfortunately.
 

Mhin Ra

Veteran
Veteran
Joined
Aug 17, 2015
Messages
61
Reaction score
18
First Language
English
Primarily Uses
RMVXA
I think I can probably give that a whirl; I'll share something tomorrow :) I'd thought clearing that array was the issue, but I didn't read enough to realize it had to happen after revive.
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
2,604
Reaction score
1,946
First Language
English
Primarily Uses
RMMV
I think I can probably give that a whirl; I'll share something tomorrow :) I'd thought clearing that array was the issue, but I didn't read enough to realize it had to happen after revive.
You actually need to do it in a different method:

Code:
def add_state(state_id)
    if state_addable?(state_id)
      add_new_state(state_id) unless state?(state_id)
      reset_state_counts(state_id)
      @result.added_states.push(state_id).uniq!
    end
  end
That last line is the one you want to suppress if the character's been revived.
 

Mhin Ra

Veteran
Veteran
Joined
Aug 17, 2015
Messages
61
Reaction score
18
First Language
English
Primarily Uses
RMVXA
Ah; I had hit one too low in the method stack it seems ;) So, I think just moving my logic up to add_state is the right fix and essentially what I think I meant to do the first time. Also, I made it usable without scripting. If you define a state that is this 'survive an attack' thing and then put it's id in @@catLivesStateId, it should allow you to give this resistance using the normal addState stuff. It might even work for enemies, although (TBH) I didn't try that.

So, try this:
Ruby:
class Game_Battler
  attr_accessor :catLives

  @@catLivesStateId = 27

  def hasCatLives?
    return state?(@@catLivesStateId)
  end

  alias :mrCatLives_addState :add_state
  def add_state(state_id)
    if state_id == death_state_id && hasCatLives?
      @catLives -= 1
      revive()
      remove_state(@@catLivesStateId) if @catLives <= 0
    else
      if state_id == @@catLivesStateId
        @catLives = 0 if @catLives == nil
        @catLives += 1
      end
      mrCatLives_addState(state_id)
    end
  end

  alias :mrCatLives_eraseState :erase_state
  def erase_state(state_id)
    @catLives = 0 if state_id == @@catLivesStateId
    mrCatLives_eraseState(state_id)
  end
end
And then my test event looks like this:

1594921458707.png

The point being 'CATLIVES' is state 27, in my test, and I add it twice. So, Selenia survives two attacks, then dies on the third. I think that it's fairly easy to get states to be applied as a result of items or attacks or skills or whatever, so that's probably a good UX?

Also note that removing the state will remove ALL cat lives, not just one. I think that's probably fine; if you want to remove just one, deal a ton of damage, I suppose ;)

Anyway, lemme know how it works!
 
Last edited:

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,573
Reaction score
6,497
First Language
Indonesian
Primarily Uses
RMVXA
I don't like fiddling with add/remove states. It gets clunky overtime.
Why not overriding the actual damage dealt
Code:
class Game_ActionResult
  alias lethal_attack_dodged make_damage
  def make_damage(value, item)
    if item.damage.to_hp? && @battler.state?(999) <-- your immortal state id
      value = [@battler.hp - 1, value].min
    end
    lethal_attack_dodged(value, item)
  end
end
 

Mhin Ra

Veteran
Veteran
Joined
Aug 17, 2015
Messages
61
Reaction score
18
First Language
English
Primarily Uses
RMVXA
That may very well be a much better approach. Like I said, I do not use the RPG Maker battle system in my game, so yesterday was the first time I ever saw this code ;) It's very possible that overloading states gets awkward over time. My combat engine makes fairly heavy use of my own states system, which is prob why I gravitated there. But it looks substantively different from what's in the base engine.
 

RCXDan

Champion of Brightmoon Tor
Veteran
Joined
Jan 4, 2019
Messages
170
Reaction score
311
First Language
English
Primarily Uses
RMVXA
I am extremely fascinated by the results we've gotten for this.

Here's what I got:

Out of the two methods, @TheoAllen's is cleaner and more effective. But I can't help but like @Mhin Ra's cat lives version barring the death message bug.

By itself the script can be a little cumbersome, since it's not additive (a cat life is set as-is, and is easily replaced by higher or lower values), but due to the combination of other scripts I have (Shaz's State Commands and Yanfly's Base Troop Events) it has quite a lot of versatility.



(Ignore the first variable, that's for something else)

Pictured above is a Base Troop Event that triggers in every fight thanks to the Yanfly script. What this in particular means is that Madeline starts every fight with Sturdy as long as her health is over 50%.

It's not tied to a particular state since it's a script call, but I can tie the effect to a state if I felt like it.
 

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,573
Reaction score
6,497
First Language
Indonesian
Primarily Uses
RMVXA
Here is the equivalent code for that
Code:
class Game_ActionResult
  alias lethal_attack_dodged make_damage
  def make_damage(value, item)
    if item.damage.to_hp? && @battler.actor? && @battler.actor_id == 99 && @battler.hp_rate > 0.5
      value = [@battler.hp - 1, value].min
    end
    lethal_attack_dodged(value, item)
  end
end
If you can code, you just need to edit the conditional branch inside the script.
 

RCXDan

Champion of Brightmoon Tor
Veteran
Joined
Jan 4, 2019
Messages
170
Reaction score
311
First Language
English
Primarily Uses
RMVXA
Edit: Actually, disregard what I said.

Mhin Ra's second code not only works, but it's pretty good. I just now got to testing it.
 
Last edited:

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Ami
--- Diary ---

M.Mage: It's the F.Mage's Diary. While she isn't here,i can read it.

May, 10: I'm hurt after the battle with the Minotaur. But luckily,F.Healer heal me with her Heal-2. That why,i Fall in Love with her.

M.Mage: Eh???
So... some of my Desktop hardware has kicked it apparently (still trying to figure out what and how at the moment :/ ) .... yay?
Stream will be live shortly with some Darkest Dungeon! Feel free to drop by!
Made a HUGE (YYOOOOJJ) Update to Monstructs and moving towards a Steam Early Access release!

Forum statistics

Threads
104,225
Messages
1,004,810
Members
135,740
Latest member
Animalblack
Top