Closed Roguedeus closed 9 years ago
What do you mean?
If the methods you pointed to, locking the actor selection due to AP's remaining, didn't lock selection before my changes, why are they doing so now, when it seems to me I haven't made changes to impact BattleManager.actor_index
.
I expected it to act the same.
Previously, an actor was not selectable because they had no actions. Now, they are not selectable because they have no AP. (Or at least I am trying to do that). But the whole time, the player was able to shift between any actor that wasn't already un-selectable. So why isn't that the same now? I can't see what I broke.
You didn't break anything. If you start a battle and no one has selected any actions yet, you can freely change between Eric and Natalie.
It's once you select Eric, you are locked into Eric. Note that by "lock" I mean the battle manager always selects Eric as the next actor that can move.
But before I change it, you could switch in between selections.
You were able to select Erics first action. (It would occur) You were able to select Natalie. Then finish with another Eric... Or another Natalie if she had AP and the party wasn't capped yet.
Its broken. And I am not sure what I did to cause it.
I updated the demo with my latest code. Including a few fixes and a lot more notes. http://www.roguedeus.com/Stuff/New_FTB_Demo.zip
In my full build, I am still not able to locate where in the hell the actor index is being touched outside of the obvious. Its even worse than the demo, in that now I can't even select between the current actors before the first selection is made... Broken, BROKEN.
And I feel like my brain is is stuck in an infinite loop.
Sounds like a good time to delete the script and start over with the new insights lol
I tried that earlier... Much of what you see in the new demo, the little fixes, are a result. I effectively re-wrote it, via cut/paste with adjustments, just to make sure I followed the flow. And I do. I can track pretty much everything from battle start, to skill selection, to next_command iteration...
But obviously, I am missing something significant, and I can't figure it out. It seems like it should be working. But its not. That is the most frustrating thing of all.
Its driving me bonkers.
I typically do something simple here
For restarting scripts, I wouldn't even copy/paste code from a broken script to a new one. I don't know what might be wrong after all. Forcing you to re-write the same logic again from scratch should make you think about whether it's actually doing what you want it to do.
Ok... Time to try and tackle this today.
Starting from scratch... /ugh
I am going to try and break the actor selection and then repair it, before changing anything else. Hopefully, isolating that particular process will help me see WTH I am missing here. ;)
edit: Apparently, today was not a good day to start... :( I am guessing tomorrow might not either...
Ok, time to force myself to do this... /sigh
Can you explain why this method utilizes this loop structure?
def self.next_command
begin
if !actor || !actor.next_command
@actor_index += 1
return false if @actor_index >= $game_party.members.size
end
end until actor.inputable?
return true
end
IOW: Is there an easier to read way to do this?
I think I found my problem... Now, to iron out the particulars.
The only semi-issue with the fix is that the actor index will keep iterating to the next actor regardless of if the current actor still has AP to spend. But its as simple as hitting the back arrow key, to select the next action.
Now... I need to figure out how best to remember the last selecting actor, and which method to mess with when undoing its previous selection.
It's basically a do ... while
loop. Some people like it I guess since you always run the body before you check the condition. I don't think it makes a difference if you just put it in a regular while loop.
For your selection problem, it is a design decision, but this is how I would imagine it to work:
while you have AP
if this actor can move
select action
else
go to next actor
end
end
This would probably be something that the battle manager uses when it's choosing the next actor.
When I am finished with this plugin, I have some serious re-evaluations to do on my feature list...
I have a veritable tsunami of OH SHIT slamming me in the face, if I expect to get ANYTHING resembling a finished game done any time soon...
Its hard to tell how much of my procrastination is fueled by the uncertainty I have engineered into my project, due to its plethora of potential features, and how much is the weight of my own character flaws.
Ya, there's a lot of things that would be nice to have, but implementing it would take a certain amount of time.
I'd determine whether the benefits of implementing it would offset the amount of time and effort required to put into it.
I do the same with my scripts. It would be nice to have all of these different features, but sometimes I just cut half of them out and end up making a separate script focused on only one specific feature and release that.
Maybe over-time I'll implement each part one by one and get the whole system, but until then, people would only have parts of it to work with.
Once I finely get to finishing this, I just realized I am going to have to redo enemy target determination. The current TGR
param is just to clunky for the details I am engineering into my classes.
Ugh. I really need to put my head down and get some work on this done.
Ok, I am at my wits end... I am going back to basics.
In order to avoid becoming regularly overwhelmed, bouncing from one mechanic to the next, I am scrapping the idea that I am going to make a 'Complete' game right out of the gate.
Instead, I am going to make 'PART' of a game, focusing on a core mechanic (such as Battle Mechanic) and work on it until I am satisfied with it. Release a demo to solicit feedback. Make any improvements that feedback provides. And then move on to the next 'PART' of a game...
I will repeat this, until I have enough core parts fleshed out to begin assembling them together.
Since I am planning a sort of Strategy RPG, where battle is the dominant activity, I figure the Battle Mechanic should be my first 'PART' to focus on.
Here goes. :)
I am also going to end up re-writing a lot of my stuff... I am going to try and focus on best practices. Primarily, one script does one thing... Single Responsibility Principle. Also that each script should be dependent only on the part it plugs into. Not on other plugins.
At some point, programmers come to appreciate all that agile and SOLID principles whether they simply read it in a book (lots of good material) or they figured out some of these "best practices" through hard trials. I was fortunate enough to read about it, but I guess some others might not.
Iterative and incremental approaches to developing a game (or any software...or anything for that matter) typically make sense (provided releasing information will not cause issues, such as competition getting some intel)
If people don't like it, it's better to find out early on before you invest too much time into it. Only time I would invest time into something that might not be too useful is if it provides learning opportunities.
All of my scripts are designed based on single responsibility, from the functionality down to the actual implementation. Minimal dependencies and maximized flexibility allows you to develop a system in different parts and integrate them without having to worry too much.
If you're going to create a large system, it doesn't really matter whether you write them as one system, or as a bunch of different parts right?
If something works, and you know it works, then you have one less thing to worry about when something doesn't work. Why? Because you've secured an escape route. The worst thing you can do is throw yourself in the middle of unchartered territory and when one component doesn't work, you can't pinpoint the source because you're not sure if existing code works either.
Your work is what has inspired me to make the change. I've wanted to do it for a while, but hadn't reached a point were I was ready to.
I am also going to take the opportunity to re-evaluate my reliance on Yanfly's battle scene. Since I have started from as scratch as I can (while cannibalizing my old work) I am now open to the possibility of changing the 'alignment' of the battle scene.
In order to make my life a little easier, I am going to focus on non-portrait based UI's. If I can.
Do you have any favorites? Preferably ones that support state and element popups.
Edit: I think I might just make portraits of zoomed in sprites... Its a dirty hack, but it will do as a temp fix.
I don't have any particular favorites. I think any UI that does its job and is presented well, is OK. Of course if the actors you're working with are beautiful and you want to see them more often, you might build your UI around showing portraits as much as possible, whenever you can (command selection, skill cut-ins, victory pop-ups, etc)
At this point, I would consider just building the UI from ground-up based on what you need and how you want to convey your game.
All battle systems can be decomposed into smaller components. For example, a quick analysis of yanfly's battle system will show you
These are not really things that you necessarily need to provide as one script. It's definitely "easier" for end-users who are interested in the whole package, but for more advanced users, I would prefer to offer each component separately (and provide a "whole package" only for convenience).
It's not entirely difficult to build the system. What I like about yanfly's battle system is that it focuses on user experience. But other than that, it's not as complex as it seems since it's mainly a derivative of the default battle system.
Yami's symphony engine, for example, adds animations to the mix, which is an extra layer of complexity. Theo and Victor's animated battle systems offer really complex animations, which is probably something I would buy/use rather than try to make myself.
At the moment, I do not plan a relatively static party composition that is typical of JRPG's. The variety will be fairly random and as a result, attempting to find appealing portraits for each will prove prohibitive. To say the least.
The serious lack of side animated battlers is also why I am shying away from those more complex formats.
It seems that the simple, but acceptable, Yanfly standard fills the need. Ive gone ahead and used his Visual Battlers script. Thus, removing the portraits from actors, leaves their square blank in the battle scene and the visual battlers script places their sprite looking up at the enemy battlers.
Its a little crude. But its better than nothing.
Come to think of it, this may actually prove fortuitous. The changes I have made to the health bars (not shown here), can now be done without obscuring the actors portraits (since they are blank).
Note: There is an annoying visual artifact with the font though... Its getting clipped at the very front.
(Looks like Mithran - Text Cache
fixes the visual font issues. Forgot about that.)
Hah... I've already found two non-crash bugs I had completely missed, due to refactoring my code. And I've only done two of my scripts... shudder
On second thought, I've gone ahead and used Theo's Side Battle System, with a small tweak.
Once its set up its rather simple to use. Everything remains default, unless I make a skill use a specific sequence. It also resolves faster than default when multiple targets are attacked.
Yes, ironic that I am using a side battle system for a non-side battle scene. :p
Well, the only difference between a side-view battle system and a front-view battle system is the perspective.
That's what made me attempt it. I figured the script has actors jumping all over the screen, so it couldn't have been difficult to change the start locations and sprite orientations... It wasn't.
I am definitely going to have to rewrite some of my action resolution/damage scripts as a result though. It won't be to much.
Now that I know this works so well, even on a minimalist level, my mind is eased. I had been wrestling with doubts regarding the battle visuals.
Managed to get the Status Menu to stop shifting around between rounds, so it stays lined up with the backs of each battler. Also, found an issue with my Free Turn Patch not assigning @subject
...
Now to figure out how to undo the actions in order... Been putting this off tooo long.
Queuing the actor is easy... its finding out were to undo it that's proving difficult. FTB assumes all actions occur instantly.
Currently FTB simply returns to the party command window when the undo key is pressed. Default behavior appears to simply re-select the previous actor index, forcing actor.input
to be re-set, rather than removed.
edit:
LOL... Ace Battle Engine does the same thing... :dir4
simply re-selects the left most indexed actor for action re-selection. Nothing is ever undone.
edit2:
Seems the best way to handle this is in BattleManager.prior_command
where I changed it to check for remaining actions.
Ok... I have to stop for a while.
It works. Once. And then breaks. I am at the point were my head won't let me see why. (Act, Undo, Act, Undo... ERROR) http://www.roguedeus.com/Stuff/New_FTB_Demo.zip
actor.actions.last.name
You mean actor.actions.last.item.name
?
Yes. Thanks for pointing that out. I am not sure why that didn't dawn on me.
After fixing that print issue, it functions.
I need to figure out a work around for the :dir4
issue now... arrowing left, is equivalent to :cancel
and I either need to bypass that while allowing dynamic selection, or simply force action in index order...
It seems as though .slice!
is leaving an array with a nil
element rather than an empty array, when performed on an array with a single element. Causing .empty?
to return false.
edit: Nope... Somehow a nil objects getting pushed in...or I am just to damn tired to be doing this right now.
lol... I am doing something seriously wrong and I am to tired to think... be back tomorrow.
Fixed it within 10 minutes of sitting down at my desk...
In attempting to fix a previous issue, I had commented out input.set_attack
in command_attack
and as a result, queue_ftb_action
was getting confused on how to handle the selection.
Now, to get :dir4
to not auto call :cancel
and to simply move the selection.
edit: Also, actors with more than one AP cause issues... :p
I think it will be easier to simply disable the left/right dynamic actor selection. Its causing major issues, and without instant resolution (as in default FTB) its actually superfluous anyway.
edit: Done.
edit2: Nope I was wrong. Dynamic selection is necessary if AP's are shared by the entire party.
I am thinking that the only solution worth the time, is to cut the ability to undo action selection. This way, it is still FTB at heart (since you can't undo an instantly resolved action anyway) and its the order of resolution that's dynamic.
OK, I think this is good enough for a FUCK IT I'M DONE version... http://www.roguedeus.com/Stuff/New_FTB_Demo.zip
lol as long as it's satisfactory.
#RogueDeus 14_1118
#Last Updated 15_0205
#RDeus - Yanfly Free Turn Battle Plugin v1.00
#Includes an equivalent fix to, TheoAllen - YEA Battle Turn Fix
# If you keep the turn fix, make sure its ABOVE this plugin.
$imported = {} if $imported.nil?
$imported["RDeus-FTB-Plugin"] = true
#puts("#{$imported.size}~ (+)RDeus - Yanfly Free Turn Battler - Plugin") if $TEST
#===============================================================================
#
#===============================================================================
module BattleManager
#-----------------------------------------------------------------------------
# overwrite:
#-----------------------------------------------------------------------------
def self.next_command
begin
#ISSUE: currently next_command is functionally always true. 15_0205
if !actor || !actor.next_command
@actor_index += 1
if @actor_index >= $game_party.members.size
if $game_party.inputable?
@actor_index = 0
else
return false #if @actor_index >= $game_party.members.size
end
end
end
end until actor.inputable?
return true
end
#-----------------------------------------------------------------------------
# overwrite:
#-----------------------------------------------------------------------------
def self.prior_command
begin
#ISSUE: currently prior_command is functionally always true. 15_0205
if !actor || !actor.prior_command
@actor_index -= 1
if @actor_index < 0
return false #if @actor_index < 0
end
end
end until actor.inputable?
return true
end
#-----------------------------------------------------------------------------
# new:
#-----------------------------------------------------------------------------
def self.undo_last_ftb_action
action = actor.actions.slice!(-1)
unless action.item.nil?
actor.undo_ftb_action(action.item.ftb_cost)
end
end
#-----------------------------------------------------------------------------
#
# All potential actions are given order BEFORE any choices are made.
# If a battler has no current action (when processed), its skipped.
# Making normal FTB mode appear to be all actors THEN all enemies.
#-----------------------------------------------------------------------------
def self.make_ftb_action_orders
@action_battlers = []
@action_battlers += $game_party.members unless @surprise
@action_battlers += $game_troop.members unless @preemptive
@action_battlers.each { |battler| battler.make_speed }
@action_battlers.sort! {|a,b| b.speed - a.speed } #Battlers with actions perform them in speed order.
end
#-----------------------------------------------------------------------------
# new:
# Added to allow dynamic re-sorting of battlers.
#-----------------------------------------------------------------------------
def self.action_battlers
@action_battlers
end
end
#===============================================================================
#
#===============================================================================
class Game_Party < Game_Unit
#--------------------------------------------------------------------------
# new method: meet_ftb_requirements?
#--------------------------------------------------------------------------
def meet_ftb_requirements?
return true unless BattleManager.btype?(:ftb)
return ftb_actions_remaining > 0
end
end
#===============================================================================
#
#===============================================================================
class Game_BattlerBase
#-----------------------------------------------------------------------------
# new:
#-----------------------------------------------------------------------------
def undo_ftb_action(value = 1)
init_ftb_actions if @used_ftb_actions.nil?
@used_ftb_actions >= value ? @used_ftb_actions -= value : @used_ftb_actions = 0
end
end
#===============================================================================
#
#===============================================================================
class Game_Battler < Game_BattlerBase
#-----------------------------------------------------------------------------
# overwrite:
# Needed to not init ACTOR actions. They are now pushed on selection.
#-----------------------------------------------------------------------------
def make_actions
clear_actions
return unless movable?
@actions = Array.new(make_action_times) { Game_Action.new(self) } if self.enemy?
end
end
#===============================================================================
#
#===============================================================================
class Game_Actor < Game_Battler
attr_accessor :action_input_index #To iterate on next command
attr_accessor :actions #To allow for a push of new actions on selection.
#-----------------------------------------------------------------------------
# alias removal:
#-----------------------------------------------------------------------------
def next_command
return game_actor_next_command_ftb
end
#-----------------------------------------------------------------------------
# alias removal:
#-----------------------------------------------------------------------------
def prior_command
return game_actor_prior_command_ftb
end
end
#==============================================================================
# ? Scene_Battle
#==============================================================================
class Scene_Battle < Scene_Base
#-----------------------------------------------------------------------------
# overwrite:
#-----------------------------------------------------------------------------
def command_attack
actor = BattleManager.actor
actor.input.set_attack
select_enemy_selection #on enemy 'ok' calls next_command
end
#-----------------------------------------------------------------------------
#
#-----------------------------------------------------------------------------
def command_guard
actor = BattleManager.actor
actor.input.set_guard
next_command #<--- necessary to queue action.
end
#-----------------------------------------------------------------------------
# overwrite:
#-----------------------------------------------------------------------------
def ftb_action?
return false unless BattleManager.actor
value = true
value = false unless BattleManager.btype?(:ftb) && value == true
value = false if BattleManager.actor.nil? && value == true
value = false unless BattleManager.actor.inputable? && value == true #<--- added to stop infinite loop
value = false if BattleManager.actor.current_action.nil? && value == true
return value
end
#-----------------------------------------------------------------------------
#
# Called after every action is chosen.
# Default FTB: auto executes the most previous choice.
# Plugin: calls for the action to be queued, for action order.
#-----------------------------------------------------------------------------
# alias scene_battle_next_command_ftb next_command
def next_command
if ftb_action?
queue_ftb_action
else
scene_battle_next_command_ftb
end
end
#-----------------------------------------------------------------------------
# overwrite:
#-----------------------------------------------------------------------------
alias :prior_command_rd_ftbp :prior_command
def prior_command
if ftb_action?
queue_ftb_action
refresh_ftb_gauge
else
prior_command_rd_ftbp
end
end
#-----------------------------------------------------------------------------
# new:
#-----------------------------------------------------------------------------
def queue_ftb_action
hide_ftb_action_windows #Required to display actor status window.
actor = BattleManager.actor
@subject = actor #@subject is assigned here, for compatibility with other scripts.
item = actor.input.item #This insures that any action is 'queued' (guard, etc...)
unless item.nil?
consume_ftb_action(item)
actor.action_input_index += 1
end
end_ftb_action #Moved here from show_ftb_action_windows
end
#-----------------------------------------------------------------------------
# unchanged:
#-----------------------------------------------------------------------------
def consume_ftb_action(item)
BattleManager.actor.use_ftb_action(item.ftb_cost) unless item.nil?
refresh_ftb_gauge
end
#-----------------------------------------------------------------------------
# overwrite:
#-----------------------------------------------------------------------------
def end_ftb_action
if $game_party.inputable?
status_redraw_target(BattleManager.actor)
if !BattleManager.next_command
BattleManager.clear_actor
start_actor_command_selection
else
start_actor_command_selection
end
else
status_redraw_target(BattleManager.actor)
turn_start
end
end
end # Scene_Battle
On the bright side, I should understand the battle process much better than I would have.
I swear, this is why I try to avoid using scripts written in ways I can't follow...
Theo's Side Battle System is messing with Game_BattlerBase.refresh
somehow and I can't find how. When I remove it, refresh
is only called ONCE after a battler dies, and processes my script fine when it does.
But with his script included, refresh
is called THREE times, and the first two times its somehow incomplete. Like it stops half way through. I know because I have comments outputting to the console through the entire process, including every one of his that I can find comes close to touching refresh
, or add_state
.
He does alias an override method, in a child class like you used to do before I pointed out that it often ignored parent level aliases when done. But even when I replace his alias call with a super
call, it makes no difference.
class Game_Battler < Game_BattlerBase
# --------------------------------------------------------------------------
# Alias method : Alive?
# --------------------------------------------------------------------------
alias tsbs_refresh refresh
def refresh
tsbs_refresh #<------
if @immortal && @hp == 0
clear_states
clear_buffs
end
end
end
All I am trying to do is get this overwrite working.
class Game_BattlerBase
def refresh
state_resist_set.each {|state_id| erase_state(state_id) }
@hp = [[@hp, mhp].min, 0].max
@mp = [[@mp, mmp].min, 0].max
if @hp == 0
return if state?(coma_state_id) || state?(death_state_id)
if massive_damage? || critical_damage?
puts("\n<MostlyDead> Applying DEATH\n") #<---- This outputs
add_state(death_state_id) #<---- This never completes
else
puts("<MostlyDead> Applying COMA")
add_state(coma_state_id) #<---- But this DOES!?!?
end
else #hp must be greater than 0
remove_state(death_state_id)
end
end
end
The first two times refresh fires, it outputs "Applying Death" but never does... The third time it fires, it outputs "Applying COMA" and actually does. Like it should.
I'll mention, @immortal
is never flagged so his alias shouldn't be completing clear_states
.
SON OF A....
The moment I said that I made sure @immortal
wasn't flagged and sure as shit... IT IS SOMEHOW.
That doesn't seem to matter. Commenting out his entire refresh method, makes no difference either.
edit: I think I found it... /sigh
It is the immortal
flag... It seems that he flags ALL battlers immortal while any one of them is performing a sequence capable action.
I am guessing its to stop them from processing another effect that would break the sequence, such as an actor dieing halfway through a sequence has another hitting them 100 times... If they died on the 50th hit, it would seem silly watching the last 50 hits strike mid air... Or whatever.
Presumably, this will break almost ALL extra skill based effects, during battle, that can apply death on add_state, and equivalent battler methods. Or in other words, SEVERAL of my biggest scripts... /sigh
Its not immediately obvious to me how I can work around this either. Though its possible, because he manages to get DEATH to apply after sequences end...
Sorry for using this as a place to vent... If I hadn't figured it out myself, I would have needed some constructive feedback. ;)
I fixed the issue. And learned some of the secret sauce behind Theo's script. He is good at what he does.
Ok, its been a while since I thought about this, but I think I've been going about this wrong.
Do you know of any battle system that functions like FTB (actions are performed the moment they are selected) but that each battler in the scene (actor and enemy) act in order of speed? Each action then adds a speed factor to the battlers order (after they act) and re-inserts them into the action order queue?
The only functional example I can think of is the RPGMaker game "Skyborn" which I think was made with XP. (though I am unsure)
This might do the trick... http://forums.rpgmakerweb.com/index.php?/topic/1128-saba-kans-ao-no-kiseki-battle-system-028-and-rokans-at-bonus/ Gonna look into how well it plays with Yanfly and Theo... fingers crossed :)
You wouldn't happen to know Japanese would you? :) I need to verify 'Terms of Use' for that script... (Google Translate isn't doing a good job) http://petitrare.com/blog/?page_id=5332
Which script? On Jun 2, 2015 11:58 AM, "Roguedeus" notifications@github.com wrote:
You wouldn't happen to know Japanese would you? :) I need to verify 'Terms of Use' for that script...
— Reply to this email directly or view it on GitHub https://github.com/Hime-Works/Requests/issues/246#issuecomment-108000150 .
I am thinking of writing a plugin for Yanfly's FTB Battle Option that utilizes its AP model but maintains the speed/initiative of the default system, with a twist.
Like FTB, actors will be able to take multiple actions in a turn, dependent on the AP used in the action. But unlike FTB, each potential action point has its own initiative and actions that require multiple action points must WAIT until the total points needed reach their initiative order.
The catch, of course, is that the player will need a visual indicator so they are aware when their potential actions will fall within the order. I figure I could use Yami's - Order Gauge for this somehow.
Thoughts? Critiques? Potential issues?