Closed Roguedeus closed 8 years ago
Sounds good.
I would add, how recipes are defined.
Personally, I prefer the option of having recipes independent of the item, but result in the item. Thus you could have 'x' different recipes for the same item.
I am applying casting disjunction to spells, and adding a few new battler parameters to the default process. My first is:
cst = cast (equivalent to hit for non-spells)
It will offset mev
the way that I have hit
offsetting 'eva' now...
Essentially every action is 100% successful, unless the target counteracts it. This includes critical hits! Every attack is a critical hit, and every target is 100% cev
. Thus +10% cri
is effectively a -10% cev
for the target, and +10% cev
is essentially -10% cri
for the attacker.
In essence I am making most advanced parameters direct offsets of their opposite. This way, as battle scales, results DONT unless there is a great disparity between battler parameters. Such disparity can be engineered via buff and debuff effects.
...
Disjunction occurs when a spell caster is damaged... Not to be confused with being hit, as armor normally prevents damage.
Disjunction is a progressive state that graduates to a higher state when re-applied, and reverts to a lower state, as it wears off. The higher the state, the more likely a spell will fail when cast.
Spells will have their own 'disjunction' resistance. As will battlers of specific battle classes... Meanwhile, hybrid casters will likely suffer greater disjunction effects. Thus keeping your caster armored, and protected, is SUPER important.
This should prevent most 100% caster, party compositions. ;)
...
This is all part of the removal of default RNG to ability use.
All actions, against a defenseless target, are 100% effective. The challenge is in determining your targets defenses, and counteracting them, in order to maximize the effect of your actions.
I am about 90% done with the core of my Battle_v3 script... Oddly, minus the GUI (which I have not decided on yet) it ended up being a bigger pain than re-writing my armor script. Mainly due to the odd issues I had to rediscover with Theo's Side Battle script.
One great thing is that this fatigue system is SAA-WEET!! Like WOW... I am about giddy with ideas on how to utilize it now that its done and I can see all the applications.
Weapon size, and spell complexity can now have DIRECT impact on the longevity of a battle, via fatigue. Blow all your big hits early and fail yo defeat your targets, you might find yourself at a growing disadvantage due to fatigue... Etc...
I am also day dreaming ways of implementing a subdue mechanic utilizing fatigue! Possibly an Advanced Fatigue plugin that causes issues if you accumulate to much... Etc...
Also making a Battle tactics plugin with 2 new standard actions (like Attack) and a re-design of how counter attacking works.
Not to mention half way done with a new Advanced Elements Script....
I have code flying out my ass these days. It feels good!
Success provides motivation. Good techniques probably helps makes things smoother. On Sep 14, 2015 5:27 PM, "Roguedeus" notifications@github.com wrote:
I am about 90% done with the core of my Battle_v3 script... Oddly, minus the GUI (which I have not decided on yet) it ended up being a bigger pain than re-writing my armor script. Mainly due to the odd issues I had to rediscover with Theo's Side Battle script.
One great thing is that this fatigue system is SAA-WEET!! Like WOW... I am about giddy with ideas on how to utilize it now that its done and I can see all the applications.
Weapon size, and spell complexity can now have DIRECT impact on the longevity of a battle, via fatigue. Blow all your big hits early and fail yo defeat your targets, you might find yourself at a growing disadvantage due to fatigue... Etc...
I am also day dreaming ways of implementing a subdue mechanic utilizing fatigue! Possibly an Advanced Fatigue plugin that causes issues if you accumulate to much... Etc...
Also making a Battle tactics plugin with 2 new standard actions (like Attack) and a re-design of how counter attacking works.
Not to mention half way done with a new Advanced Elements Script....
I have code flying out my ass these days. It feels good!
— Reply to this email directly or view it on GitHub https://github.com/Hime-Works/Requests/issues/285#issuecomment-140210559 .
The preview I gave of the new mechanics isn't completely accurate anymore. ;)
I think my small change is actually better. I might be making a blog post in a few days. Once its 100% complete.
I'm thinking of allowing consumption of food and water, out of battle, to quickly remove fatigue. ;) edit: And possibly apply a state that helps remove fatigue for some time after eating. That way staying well fed, allows for better fatigue control!
How long is the fatigue script?
I'm thinking something like this
class Game_Battler
attr_reader :fatigue
def initialize
# alias stuff
@fatigue = # something
end
end
And everything else is plugins lol
Yeah. Most of the code is reading fatigue data from objects, plugging fatigue into the actual battle math, and factoring in different rates for different activities.
I want some actors to process fatigue differently when doing activities that complement their normal skills, than when doing things off role... etc... which mirrors reality a lot.
There is also an offset for level difference between battlers. Fighting higher level enemies causes more fatigue. Etc...
LEVEL_DIFF_ROLLOVER = 0.5
#The rate applied to BASE fatigue due to level difference between attacker
#and target. It can be extended as far as you desire.
LEVEL_DIFF_RATES = {
0 => 1.0,
1 => 1.1,
2 => 1.2,
3 => 1.5,
4 => 2.0,
5 => 2.5,
6 => 3.0,
}
The only reason its part of the Battle_v3 core, is its so invasive in the math. I figure I put it where it needs to be while I am completely overwriting the methods... Using the new code as easy access for future plugins.
edit: Fatigue and Parameter offsets are the largest part of replacing the default RNG of the battle system.
edit2: I am thinking I may have to create an entirely new page for the status menu, with nothing but fatigue stats... ;( It will be that important, if you wish to min/max your game. Or you can just ignore it, and eat food, etc, whenever you need to. I doubt many people ever really eyeball the expanded status screen anyway.
This is why I am still unsure how much GUI work I'll need. I will need to do a ton of play testing, and get feedback, to know what info to share and what to hide.
Battle_v3 - Core
is completed... With a few things I had not planned to include. Simply because it was prudent.
As it stands, all item effect rates and fatigue are offset via actor and target level difference. Maneuvers are any battle action (offensive or defensive) and their results are offset via current total fatigue and applicable parameter differences.
In order to achieve a good diminishing return, parameter based offsets are sqrt
divided by sqrt
.
The No.1 issue I had was re-discovering compatibility issues with Theo's scripts.
Lions share of the advanced element script is done... All element related data for an attack is stored in data classes and re-collected every attack for easy access by other scripts. Including Armor_v3 and Battle_v3... Also, to include aptitudes and State Elements (next on the list)
Elements can now be biased by rates or flat damage bonuses. All applicable resists included. Going to add popup support next.
Am I missing something obvious here?
This method errors:
def attack_elements
return @has_element.inject([]) {|x,(element, applicants)| x << element if applicants > 0}
end
this does not:
def attack_elements
temp = []
@has_element.each {|elem,count| temp << elem if count > 0}
return temp
end
Am I using inject wrong? I have done similar with arrays... Without errors.
State Elements are done... Now an actions element is considered when applying a state, in exactly the same way that it is considered when applying attack damage.
It utilizes the same basic methods from my Advanced Attack Elements script, and the methods I added for enemy level offsets on effect application.
In essence, there are now up to half a dozen or so 'situational' adjustments made to every action. Removing the need for base success.
I understand WHY developers rely on base success and onerous RNG... It is quick, and a reasonable abstract for exactly what I am coding. BUT it is also lazy, and punishing of player ingenuity. Not to mention, frustrating as all hell...
I like the idea that my CHOICES are the primary determining factor in my success, not a random number generator. ;)
For your inject
issue, inject
works by recursively calling itself and applying the operation to the result
eg:
[1,2,3].inject(0) {|r, num| num + r}
Is equivalent to
num1 + (num2 + (num3 + r))
On the first call, r
is equal to 0
num1 + r # 1 + 0 --> 1
On the second call, r
is equal to 1
num2 + r # 2 + 1 --> 3
On the third call r
is equal to 3
num3 + r # 3 + 3 => 6
And now it returns r
.
So on every iteration, r
gets passed to the next iteration.
But what happens if you don't pass anything?
Start with this
[1,2,3].inject(0) {|r, num| p [num, r] ;num + r}
It will print out
[1, 0]
[2, 1]
[3, 3]
But if you decide to return a nil instead...
[1,2,3].inject(0) {|r, num| p [num, r] ;num + r; nil}
Now you get
[1, 0]
[2, nil]
And it crashes.
This is also called a fold
operation.
Thanks for the explanation!
It just occurred to me that with this State Elements script I can essentially asign non-damage damage elements
that are used purely for effect dynamics.
A spell that causes no actual damage, but places an effect, can be assigned arcane
damage element and be subject to arcane
resistances. Plus the way I coded bias and bonus factors, multi-element effects can require multiple stages of resistance applied.
Consider an 150% arcane
effect that also happens to be 150% Fire
based. (300% / 2 = 150% rate) A 100% Fire Resist
would merely drop the application rate to 75%. (150% / 2) Thus it would need separate arcane resistance to mitigate it further.
It creates a large swath of potential interactions. The target would have to resists both, to prevent the effect.
edit:
Also, I could simply create a certain
element type that guarantees unhindered rates. Much like a certain hit type guarantees skill effect. (independent of PDR and MDR)
The above example, could then be 100% Certain
and 100% Arcane
and always have a 50% minimum chance of application.
Just noticed an error in my math... But when I fix it, I am getting a NaN
error...
I am looking at the code, and I do not see where I am multiplying an infinite.
def total_element_rate
rate = 0.0
bias = 0
@game_elements.each {|element, detail|
next if element.empty?
rate += ((detail[:rate] / [@has_element[element], 1].max) * defender_element_data.element_defense(element))
bias += detail[:bias]
}
return rate + bias
end
Everything has default init values of 1.0 or 0... None are Boolean. Yet I am returning a NaN
value.
/boggle
Not sure what I did... Took a break, came back and split it up... Now it works... (It includes a stupid math fix)
def total_element_rate
rate = 0.0
bias = 0
atk_rate = 0.0
def_rate = 0.0
@game_elements.each {|element, detail|
next if element.empty?
atk_rate = detail[:rate]
next if atk_rate == 0.0
def_rate = defender_element_data.element_defense(element)
rate += ((atk_rate / [@has_element[element], 1].max) * def_rate)
bias += detail[:bias]
}
return (rate / attack_elements.length) + bias
end
I don't see it...
Usable items rescued eval just made me feel like I was losing my mind...
I would laugh if I wasn't so irritated.
DOCUMENTING!!... Documenting............ Doc.... u.... ment... ing.....
edit: My scripts are getting to where I need to keep good use notes just to remember what I added already.
In the above issue, is it because I am potentially dividing zero? (Not by zero).
I'm not too sure about NaN. The only thing that comes to mind is when you try floating point division 0.0 / 0
or something. As opposed to 1 / 0.0
which gives you Infinity
Ok. That makes sense then.
On today's list... Complete Battle_v3 - Item Effects Adding standard effects... Something like 'Normal' attack states, only they are effects that are applied to all actions. Including Pre and Post application. Also going to throw in user targeting effects while I am in there.
I don't think I'll need to replace your User Effects
script as that can still apply to normal database assigned effects. My addition is note-tag assigned effects. I am considering piggy backing on your Pre and post effects arrays somehow... Or maybe I'll let your script be the PRE-Pre effect and POST-Post effect script... ;)
Yesterday was a roller coaster.
It seemed every time I turned around, some bit of code I had added before the weekend came back to haunt me. Suddenly, all my evals were broken (I had a bad hash key), guard was gobbling up 100% of dealt damage (I was not rounding floats), and assigned element types were almost completely broken (I had mixed up the collection loop)... Heh..
They were all, very simple oversights. Relatively easy to fix once I found out what they were. Of course, since I didn't notice them until two or more days after causing them, it was that much harder to figure out what the culprit code was.
On the bright side, Item Effects are almost done... Almost.... :)
Oh yeah... AND I finely fixed a lingering math issue with element rates.
Whats cool about the common effect script, is that I can attach them to feature objects and have them applied to all actions (with conditions) or just attach them to the usable item and have fully conditional effects. Without worrying about the database assigned effects at all.
#------------------------------------
EXAMPLES:
#------------------------------------
This note tag will cause a debuff to the attackers DEF any time one of
their physical attacks misses its target.
<common_effects>
target_user
effect: code: 32 id: 3 value1: 1.0 value2: 0
cond: e.physical? && !r.hit?
select: post
</common_effects>
edit: You can apply more than one effect in a note tag. But they need separate ones for separate options.
I remember when I first started using RMVXA and looking at the ruby code thinking there was simply no way I could understand it... I poked and poked until I got some of the simplest things to work.
My brain had a hard enough time with static typed compiled languages like C#, trying to make sense of Ruby was brain bending. I had to think in code, rather than trace the types and declarations.
Now... When I look at scripts that used to give me head aches trying to follow, I can only see how I might improve it, or wonder why they did a thing a specific way. Like a lot of Yanfly's stuff.
Then there are still some scripts you've written that I can't follow for some reason... Maybe I just give up to easily. ;)
Personally I would prefer using a tagging systems, and assign effects to each tag. Then you can mix and match tags to achieve various things.
It sounds great... But it would require a lot of thinking on how to include conditions, selections, and targets... All built into the note tag I am using.
How complex are each of those things going to be?
Most feature object assigned common effects will require a selection and a condition. Otherwise doing something like guarding or using an item will trigger it.
Selections are for sorting. Like only grabbing the effects assigned :preempt
selection for preemptive effects that are applied before item_apply processes the item. Etc...
Conditions are as complex as you want... The example I gave is rather simple.
Flagging target_user
is equivalent to your user effects script. But with the added bonus of built in conditions and not having to count database effects.
I understand that you could conceivably define a tag for every combination... But that would get rather cumbersome. Or at least I can't easily think of an intuitive solution.
sub-tags
?Something like; an item has the sword
tag and an optional note stating that tag has sub-tags
. Which may be a set of constants that can qualify a tag in various ways. Rather than have a different sword
tag for each type of sword, you have sword sub-tags
that IF WANTED can be queried.
A battlers tag pool, will keep track of all existing tag - details
such that if a script has specific use dependent information, every time it sees a tag, it can 'cache' that data in the tag for easy retrieval. The most obvious being the number of said tags in the pool in relation to other tags. Thus a battler trait might be that they gain a bonus any time they have more of tag-x
than tag-y
... Or maybe they gain a bonus for every tag-x
... etc... But the data can be anything dependent on that tag, as once the tag has a 0 count
that information is ignored. Like a self regulating switch system.
The tag
+ sub-tag
process might be used as the system you suggest. Using tag combos to dictate features, effects, etc...
Yes. So for example, you have a sword
and a axe
tag.
You tag all your swords with sword
and all your axes with axe
. They would then inherit properties that are assigned to each tag.
Note that any sub-tag can be converted into a tag by using a common delimiter. However, sub-tags may be preferred because you can then re-use them.
Would there be some reason why sharp-sword
and sharp-axe
is not as versatile as having a separate sharp
sub-tag?
Only in that I amusing symbols to reduce memory and increase speed. And rather than having:
#20 tags
:sword_sharp, :sword_dull, :sword_magic, :sword_fire, :sword_ice,
:axe_sharp, :axe_dull, :axe_magic, :axe_fire, :axe_ice,
:dagger_sharp,:dagger_dull, :dagger_magic,:dagger_fire, :dagger_ice,
:spear_sharp, :spear_dull, :spear_magic, :spear_fire, :spear_ice,
#9 Tags
:sword, :axe, :dagger, :spear
:sharp, :dull, :magic, :fire, :ice
The variety could multiply into hundreds really quickly, without separating them.
Oh... I might have missunderstood a little.
The battler has a tag pool... All tags from all sources, are pooled. If you have a battler with sword
and sharp
tags, there is no way to know they are related. Unless you saved it as sword
+ sharp
as a tag + subtag.
Yes I was referring to having lots of combinations of every possible tag + sub-tag. That's one of the main drawbacks.
With tags done, I just completed the core of the Advanced Damage script... Remaining:
Advanced Damage implements Damage Core (Core param damage methods for damage formulas), Damage Delivery (Factoring in the means of attack to accuracy vs target mobility) and Damage Nature (How the damage is finely applied to the target, upon arrival)
However, in order to make Casting and Aptitudes work completely, I'll have to finish the core of my State Mechanic... It both reply on some form of alternative state tracking.
I put in 7 hours (from 6am to 1pm) today and I am about to do more... And I am actually NOT fatigued in any way.
This is a first. There was once a time when any more than 3 hours of coding made my head hurt.
It is an odd feeling. Doing something that once frustrated me more than not, and actually enjoying it.
/boggle
#-----------------------------------------------------------------------------
# new: 15_0924 last: XXXXX
#-----------------------------------------------------------------------------
def add_parameter(param_sym, value)
param_id = RDeus::RDeus::PARAM_TABLE[param_sym]
if param_id < 10
add_param(param_id, value)
elsif param_id < 20
add_xparam(param_id - 10, value)
elsif param_id < 30
add_sparam(param_id - 20, value)
else
add_cparam(param_id - 30, value)
end
end
I am trying to build a dynamic custom parameter script... Just because. ;)
This was a pain to figure out how to do. But oddly enough, I enjoyed it!
#-----------------------------------------------------------------------------
# new: 15_0924 last: XXXXX
# <cparam> </cparam>
#-----------------------------------------------------------------------------
def custom_parameter(cparam_id)
unless @custom_param == nil
return @custom_param[cparam_id] || 0.0
end
@custom_param = Array.new(RDeus::AdvParams::CUSTOM_PARAMS.length) {0.0}
self.note =~ /<cparam>(.*?)<\/cparam>/im
if $1
$1.strip.split(/[\r\n]/).each {|cparam|
next if cparam.empty?
RDeus::AdvParams::CUSTOM_PARAMS.each {|param, id|
cparam =~ /#{param}:\s*(\d+)/i
if $1
@custom_param[id] = ($1.to_i * 0.01) if $1
break
end
}
}
end
return @custom_param[cparam_id] || 0.0
end
end
At the moment I only need new xparams...
There is already built in permanent parameter increases for the base 8, but none for the other parameters... So I just added that.
Usable item effect...
#-----------------------------------------------------------------------------
# new: 15_0925 last: XXXXX
# <add_parameter: param_sym, value>
#-----------------------------------------------------------------------------
def effect_add_parameters
return @add_parameters unless @add_parameters == nil
@add_parameters = {}
regex = /<add_parameter:\s*(.*)\s*,\s*(.*)\s*>/i
self.note.scan(regex).each {|params|
next if params.empty?
@add_parameters[params[0].strip.to_sym] = (params[1].to_i * 0.01)
}
return @add_parameters
end
This uses the add_parameter
method above.
#-----------------------------------------------------------------------------
# new: 15_0925 last: XXXXX
#-----------------------------------------------------------------------------
def process_effect_paramaters(user, item)
#ADD PARAMETERS...
if item.has_add_paramater?
item.effect_add_parameters.each {|param_sym, value|
add_parameter(param_sym, value)
}
end
end
edit:
Just noticed a small improvement... Moved the value math to the add_parameter
method, rather than the items effect.
This makes it so that I don't need to even use the default add param special effect. And it includes all possible parameters. Including custom ones.
changed the buff and debuff mechanic so that they do not overwrite each other, but instead offset each other... If you have 2 buffs and get 1 debuff added, it merely reduces your buffs to 1.
Also added purge buff and purge debuff actions, to make up for the absence.
#-----------------------------------------------------------------------------
# overwrite: 15_0924 last: XXXXX
#-----------------------------------------------------------------------------
def add_buff(param_id, turns)
return unless alive?
puts(" add_buff(#{param_id}, #{turns})")
if param_id < 10
@buffs[param_id] += 1 unless buff_max?(param_id)
if @buffs[param_id] > 0
overwrite_buff_turns(param_id, turns)
@result.added_buffs.push(param_id).uniq!
end
elsif param_id < 20
@xbuffs[get_param_id(param_id)] += 1 unless buff_max?(param_id)
if @xbuffs[get_param_id(param_id)] > 0
overwrite_buff_turns(param_id, turns)
@result.added_xbuffs.push(param_id).uniq!
end
elsif param_id < 30
@sbuffs[get_param_id(param_id)] += 1 unless buff_max?(param_id)
if @sbuffs[get_param_id(param_id)] > 0
overwrite_buff_turns(param_id, turns)
@result.added_sbuffs.push(param_id).uniq!
end
else
@cbuffs[get_param_id(param_id)] += 1 unless buff_max?(param_id)
if @cbuffs[get_param_id(param_id)] > 0
overwrite_buff_turns(param_id, turns)
@result.added_cbuffs.push(param_id).uniq!
end
end
refresh
end
Did my best to use the same methods as the default system.
Aside from some new icons for the x and s params, it appears to be working great.
It is in addition to the normal buff/debuff effects. Not that I would use the default one for anything now, but I did it for the sake of compatibility.
NOW, I can move into the Battle Tactics script.
I just realized that for some time now I have been including lambda calls inside note tag methods... presumably to reduce the number of methods I needed to write. But now, I either need to re-write them or not pre-load the note tag... :(
We have Element Damage... And
UsableItem
Effects, like add state, etc... But nothing combined.What if, a stun wasn't just a stun, but an ICE stun? All rates are effected first by element resistance, and then by effect resistance. Thus a target 50% resistance to ICE, and 50% Resistance to Stun, has a 25% total resistance against ICE Stun.
This is just a simple example. But it would make certain effects able to be applied much more liberally, when something Immune to an element, is by extension also immune to all that elements linked effects.
Meanwhile, an EARTH Stun, will work fine... etc.
Elements are purely cosmetic. It would be linked to element ID's and thus can be easily extended.
Now... How would the easiest way to implement it be?
If the effect is a state, the note tag could be on that state... But then, it would require every state of every element to be individually defined. What if the link were made on the
UsableItem
?Thus, only one state is needed, and can be applied under different circumstances. Kind of like conditional effects.
This would mean that each blind effect could be assigned a different element ID dependency. Or the same dependency, under different conditions... etc...