Currently I am creating a game with a few people, as many of you are also doing, and a primary goal I have is to make the game at least somewhat unlike the generic RPG maker game that is offered to you. In my endeavor I believe I have really screwed myself with ambition. I introduce you to the faith system. The faith system is designed on a system where exp is called faith, and this faith can be lost and or gained depending on the type of enemy you defeat. This system is designed to make you be able to level up to 50 and become more holy or level down to -50 and become more demonic. Sadly I have struggled with this script for approximately 2 weeks now. So allow me to offer the good news first
A. I changed exp to faith
Its always called faith
B. I figured out how to make you lose faith in battle but not by enemy type
C. And if I sort of mess up the game I can make you be in the negative levels.
Now what I need to figure out is
A. How to distinguish between two enemy types
B. Produce skills for the negative levels
C. Make myself level down
D. Allow stats to continue to work even when in the negatives.
I've been reading how to program ruby and have tried many a script to no avail so if someone could offer me either help and or guidance I would greatly appreciate it.
Faith System
● ARCHIVED · READ-ONLY
-
-
You would need to figure out how to level in both ways. Can't help you there, would likely require a script, I don't know.
However, if you make 50 neutral and make the scale Evil-Good be 1-99 you can use the database as it sits to make a curve that would make stats high at level one drop until they get to 50 and raise from there until high again at level 99. Wasn't sure about that, but I just tried it and it works.
Can't help you with the rest, but I hope that helps. -
I did try that the first day, and even though it works it feels kinda wrong ya know? its cause im a perfectionist the symbolism of the negatives means alot to me
But thank you alot for trying to help
If all else fails I will use your method
And give you credit where its due -
The easiest way to do this would be via script, in my opinion. Not that writing the script would necessarily be "easy". But as far as scripting goes, it wouldn't be hard to code.
Personally, I would:
1) Code out levels and experience, levels have to deal with stats and skills and all kinds of stuff, so changing levels around frequently would make the game near impossible to balance right.
2) In the place of levels, create a new variable called "Faith", I'd call it karma or alignment or something else, just because having negative faith doesn't make sense to me, but it's your game :p so you decide.
2.5) Make a gauge for the "Faith" level, if you want, if not you could just display it as a number like levels would. (If this makes you wonder "Why not just use levels then?", it's because the way levels are coded to affect other stuff. Creating something brand new and only setting connections that are needed would be easier).
3) Make notetags for enemies so you can designate them "good" or "bad" or whatever. You could even go so far as to use notetags to provide the new "Faith" number's, version of exp you get per enemy killed. Let's call it FP (Faith points). You could then have the gauge/number from 2.5 change according to the number of FP each character has.
4) Skills can easily be "attached" to the new "Faith" variable number. Meaning that when you hit a certain level, you can have the script add or take skills from the actor.
5) Stats are the hard part now, only because I can't really think of a way to handle them with your system. I would need more information. Say an actor drops from 25 to 24 "Faith". Do they lose stats? Just because they are becoming "evil" or whatever doesn't necessarily mean they should be weaker, right? If that's true, then what are the stats based on since there aren't any levels? Unless you like the idea of just keeping stats the same per actor throughout the game, and letting equipment make the changes (it would probably be easier to balance that way?). If that's not a viable option, then I don't know. You tell me!
P.S. I may forget to come back to this thread, so please quote my post if you respond, so that I get a notification and can make sure that I see your response!
Also, how much ruby/RGSS3 do you know? I mean the concepts I listed aren't hard to code at all, but if you only know a tiny bit about ruby or RGSS3, then it may be too hard of a task for you. -
I definitely get what you mean, I was thinking the same thing when I mentioned it, but I thought I would bring that up just in case it hadn't occurred to you.I did try that the first day, and even though it works it feels kinda wrong ya know? its cause im a perfectionist the symbolism of the negatives means alot to me
But thank you alot for trying to help
If all else fails I will use your method
And give you credit where its due -
I wouldn't think of Faith as being negative as much as being a Good/Evil marker, from the way you've described it. To me, the concept of "negative Faith" is a contradiction in terms. The lowest possible is No Faith (i.e. 0).
It's more like "You can be Good from 0-50 or Evil from 0-50"
You would probably need to parse notetags to make an enemy "type", then the type would be associated with the specific enemy.
Here is a bit of code I use to parse the notetags and one of my smaller scripts that uses it.
The notetag parser looks for tags like this, in the Yanfly format:
<tag attribute="value">
Spoiler####################################################################
# Module which reads XML formatted note tags and returns them as
# HashMaps
module Tag_reader
###################################################################
# Represents a single XML node
class XML_node
#####################################
# Constructor
def initialize(name)
@name=name
# Set of name=value pairs
@attributes={}
end
###################################
# Adds an attribute
def add_attribute(name, value)
@attributes[name]=value
end
###################################
# Returns this as an XML string
def to_s
result="<"+@name
@attributes.each {
|key, value| result += " "+key+"=\""+value+"\""
}
result += " />\n"
return result
end
attr_reader :)name)
attr_reader :)attributes)
end
#######################################################
# Reads a set of XML tags
class XML_Reader
def initialize()
@nodes=[]
end
##########################################################
# Reads the XML tags in note_string. Does nothing if the
# note string is empty or nil. Returns the set of nodes read
# from the note_string. This may be empty
def read(note_string)
@nodes.clear
if (note_string == nil)
return @nodes
end
note_s=note_string.to_s.strip
# Ignore empty strings
string_len=note_s.length
if (string_len == 0)
return
end
index=0
worker=""
right_index=0
node_name=""
# Parse the XML string
while (index < string_len)
# Search for < mark
if (note_s[index] != '<')
index += 1
next
end
# Find the > mark after the < mark
right_index=note_s.index("/>",index)
if (right_index == nil)
right_index=note_s.index('>',index)
if (right_index == nil)
break
end
end
# This is a string from < to >
worker=note_s.slice(index, right_index-index+1)
worker=worker.strip
# Find name="value" pairs
# Skip the <name part of the XML
attr_index=worker.index(' ')
node_name=worker.slice(1,attr_index).strip
new_node=XML_node.new(node_name)
while (worker.length > attr_index)
if (worker[attr_index] == ' ')
attr_index += 1
next
end
value_index=worker.index("=\"", attr_index)
if (value_index == nil)
break
end
# Backspace to find the previous space or < mark - start of the
# attribute
attr_start_index=value_index-1
while (worker[attr_start_index] != '<' &&
worker[attr_start_index] != ' ')
attr_start_index -=1
end
# Get to the start of the attribute name
attr_start_index += 1
# Skip the =" marker after attribute name
second_quote=worker.index("\"", value_index+3)
if (second_quote == nil)
break
end
attr=worker.slice(attr_start_index, value_index-attr_index)
value=worker.slice(value_index+2, second_quote-value_index-2)
new_node.add_attribute(attr, value)
attr_index = second_quote+1
end
@nodes << new_node
index=right_index+1
end
return @nodes
end
end
end
# And an example:
#================================================
#
# Script: SwitchSetter
# by: whitesphere (whitesphere@comcast.net)
# July 5 2014
#================================================
=begin
================================================================================
Description: Sets or unsets groups of switches when the map is entered
--------------------------------------------------------------------------------
History
v1.0 (2014/07/10)
Initial release
--------------------------------------------------------------------------------
Terms of Use
- You are free to use this script for non-commercial projects.
- For commercial projects, at least contact me first.
- This script is provided as-is. Don't expect me to give support.
- Reported bug will be fixed, but no guarantee on requested features.
- No guarantee either for compatibility fixes.
- Give credit to whitesphere (me), and do not delete this header.
--------------------------------------------------------------------------------
QUICK START:
Add a note tag in the following format to a Map:
<switch on="1,2,3" off="4,5">
or
<variable set="1=23, 2=34" >
or
<common_event call="1">
or
<common_event call="1,2,3">
Common event executions take place after all switches and variables are
set.
The numbers are the Switch IDs to turn ON or OFF.
For variables, the number is the variable ID, the value after the = is what
the variable will be set to
--------------------------------------------------------------------------------
Below are the end-user SwitchSetter script functions:
Not Applicable
--------------------------------------------------------------------------------
=end
module SwitchSetter
# Helper function which tries to convert any Ruby object to a true or
# false value
def self.to_b object
if object == nil then
return false
end
if object.respond_to?:)to_s) then
obj_str=object.to_s.downcase.strip
if obj_str == "true" || obj_str == "yes" || obj_str == "on" ||
obj_str == "t" || obj_str == "y" || obj_str == "1" then
return true
end
return false
end
if object.respond_to?:)to_i) then
obj_int=object.to_i
if obj_int == 0 then
return false
else
return true
end
end
return true
end
###############################################################
###############################################################
# Encapsulates all entries for a single Switch or Variable
class Value_holder
attr_reader:)value)
attr_reader:)id)
def initialize(id, value)
@id=id.to_i
@value=value
end
def to_s
result="id="+@id.to_s+", value="+@value.to_s
return result
end
end
###############################################################
###############################################################
# This class handles the set of switches and variables
class SwitchVarHolder
# Constructor
def initialize
@switch_set=[]
@variable_set=[]
@common_event_set=[]
end
# Clear the sets
def clear()
@switch_set.clear
@variable_set.clear
@common_event_set.clear
end
def load_map(switch_set, variable_set, common_event_set)
@switch_set.clear
@variable_set.clear
@common_event_set.clear
if (switch_set != nil)
switch_set.each {
|entry| @switch_set << entry
puts("Loaded switch entry "+entry.to_s)
}
end
if (variable_set != nil)
variable_set.each {
|entry| @variable_set << entry
puts("Loaded variable entry "+entry.to_s)
}
end
if (common_event_set != nil)
common_event_set.each {
|entry| @common_event_set << entry
puts("Loaded common event entry "+entry.to_s)
}
end
# Update the switches
@switch_set.each {
|entry| if ($game_switches[entry.id] == nil)
next
end
$game_switches[entry.id]=SwitchSetter::to_b(entry.value)
}
# Update the variables
@variable_set.each {
|entry| if ($game_variables[entry.id] == nil)
next
end
$game_variables[entry.id]=entry.value.to_i
}
# Queue up the common events
@common_event_set.each {
|entry| $game_temp.reserve_common_event(entry.id)
}
end
end
def self.init()
@@instance=SwitchVarHolder.new()
end
def self.load(switches, variables, common_events)
@@instance.load_map(switches, variables, common_events)
end
def self.started_everything?
if (@@instance != nil)
return true
else
return false
end
end
end
SwitchSetter::init
# Add the accessors to get the switches to modify
class Game_Map
attr_reader :)map_id)
alias SwitchSetter_setup setup
def setup(map_id)
SwitchSetter_setup(map_id)
# Load the tile to region mappings
SwitchSetter::load( switch_settings(),
variable_settings(), common_event_settings())
end
# We fetch these from the RPGMap
def switch_settings
return @map.switch_settings
end
# We fetch these from the RPGMap
def variable_settings
return @map.variable_settings
end
# We fetch these from the RPGMap
def common_event_settings
return @map.common_event_settings
end
end
class RPG::Map
def read_note_tag_as_nodes
if (@node_set == nil)
reader=Tag_reader::XML_Reader.new
@node_set=reader.read(@note)
end
return @node_set
end
# Returns the current switch settings
def switch_settings
if (@switch_settings != nil)
if (@switch_settings.empty?)
return nil
end
return @switch_settings
end
@switch_settings=[]
nodes=read_note_tag_as_nodes
if (nodes == nil)
return nil
end
nodes.each {
|current|
if (current.name != "switch")
next
end
on_string=current.attributes["on"]
off_string=current.attributes["off"]
if (on_string == nil && off_string == nil)
next
end
if (on_string != nil)
group=on_string.split(",")
group.each { |single|
new_entry=SwitchSetter::Value_holder.new(single, "true")
@switch_settings << new_entry
}
end
if (off_string != nil)
group=off_string.split(",")
group.each { |single|
new_entry=SwitchSetter::Value_holder.new(single, "false")
@switch_settings << new_entry
}
end
}
return @switch_settings
end
# Returns the current variable settings
def variable_settings
if (@variable_settings != nil)
if (@variable_settings.empty?)
return nil
end
return @variable_settings
end
@variable_settings=[]
nodes=read_note_tag_as_nodes
if (nodes == nil)
return nil
end
nodes.each {
|current|
if (current.name != "variable")
next
end
set_string=current.attributes["set"]
if (set_string == nil)
next
end
group=set_string.split(",")
group.each { |single|
name_value_pair=single.split("=")
if (name_value_pair.length < 2)
next
end
new_entry=SwitchSetter::Value_holder.new(name_value_pair[0],
name_value_pair[1])
@variable_settings << new_entry
}
}
return @variable_settings
end
# Returns the current common event settings
def common_event_settings
if (@common_event_settings != nil)
if (@common_event_settings.empty?)
return nil
end
return @common_event_settings
end
@common_event_settings=[]
nodes=read_note_tag_as_nodes
if (nodes == nil)
return nil
end
nodes.each {
|current|
if (current.name != "common_event")
next
end
set_string=current.attributes["set"]
if (set_string == nil)
next
end
group=set_string.split(",")
group.each { |single|
common_event_settings << single.to_i
new_entry=SwitchSetter::Value_holder.new(name_value_pair[0],
0)
@common_event_settings << new_entry
}
}
return @common_event_settings
end
end
# This is to support multiple common events at once which can
# certainly happen with multiple events
class Game_Temp
attr_reader :reserved_common_events
alias :old_common_event_queue_init :initialize
def initialize
old_common_event_queue_init
@reserved_common_events = []
end
# re-write
def reserve_common_event(common_event_id)
@reserved_common_events.push(common_event_id) if common_event_id > 0
end
# Note that I don't actually need to clear it out. It's done
# by the queue.
# true if list is not empty
def common_event_reserved?
!@reserved_common_events.empty?
end
# Grab the first one, first-in-first-out order
def reserved_common_event
$data_common_events[@reserved_common_events.shift]
end
end
-
Using a good or evil side would be interesting
But it would require me to form a new class. Which means the new issue would be what should I use to change classes
Items
Events
Enemies or personal deciscion. Or should the main character have both a good and evil bar... hmmm the script would be simple enough, I think theres a few tutorials on it as well. Your script looks rather useful though my elementary level of ruby literacy makes it difficult to grasp its full potential and workings.
Regardless if I use your method coding is no longer a massive concern.
Instead the new issue would be implementation and theme.
Primarily id ask that you elaborate on your claim that my original faith system is contradicting as im very concerned with the ambiance my system gives off. So please, with all do respect, explain -
Did you even read my post, I explained a pretty simple way to go about coding it, and offered to help you out. If you don't want help coding this then... err... I guess this would make for an awkward post? Anyways, I offered, your choice.
-
Sorry sorry. For some reason your post did not actually appear last night. Wow. I am so sorry you felt ignored. I will read your post real quick and see if I can emulate it
-
If I were doing a good/evil system, I would switch classes when the player crossed the good/evil threshold, after some "probation" period. Or, if you use Yanfly's excellent scripts, you could make Good or Evil a subclass, so the attributes affect the character. So Good characters might take extra damage from Dark attacks, and Evil from Light attacks, for example.Using a good or evil side would be interesting
But it would require me to form a new class. Which means the new issue would be what should I use to change classes
Items
Events
Enemies or personal deciscion. Or should the main character have both a good and evil bar... hmmm the script would be simple enough, I think theres a few tutorials on it as well. Your script looks rather useful though my elementary level of ruby literacy makes it difficult to grasp its full potential and workings.
Regardless if I use your method coding is no longer a massive concern.
Instead the new issue would be implementation and theme.
Primarily id ask that you elaborate on your claim that my original faith system is contradicting as im very concerned with the ambiance my system gives off. So please, with all do respect, explain
I feel it is contradictory because the word "Faith" has a meaning which does not include the concept of "negative faith." The word "faithless" doesn't mean the faith is less than 0, as much as it means the faith is 0.
If I were to use Faith, per se, I might use it in a Cleric. As the Cleric is, say, possessed by a demon, the Cleric's Faith drops. As it drops, the Cleric's magic becomes weaker and weaker (since it is clearly based on Faith). When it reached 0, I'd call a Game Over screen that made clear "You lost your Faith and the demons took your soul to Hell."
But, when you say "Killing certain enemies is negative Faith, or doing certain actions is negative Faith," and you say "Faith from 0 to -50 means you're a Demon" that clearly is more good vs evil, or angelic vs demonic (NOT necessarily good or evil, BTW!).
So your interpretation looks more, to me, like Good vs Evil/Angelic vs Demonic/Law vs Chaos/etc, which is why I called it contradictory. -
A) There are a lot of different ways to "mark" an enemy as one that you'd receive positive or negative Faith for killing. I assume you're using the EXP field to determine exactly how much positive or negative Faith you receive. The easiest way would be to add an arbitrary amount (say, 50000) EXP to any enemy that would give negative faith. Then, you could say "If Exp is greater than 50000 for an enemy, subtract 50000 and then multiply by -1". So 50008 EXP would mean -8 Faith, whereas +8 Faith would simply be input as 8 EXP. Just remember that you'd need to run the evaluation for each enemy, before you total up the positive and negative Faith gains. The cleanest, best way, however, would be to use notetags and create a new "Faith Gain" property for enemies, which you would mostly copy the structure for EXP to set up. In the long run, it will help you to learn this. You could also set up an array or hash which associates Enemy ID to Faith Gain, if you don't want to use notetags.
Now, where would you actually read this "EXP" field? Check out self.gain_exp in BattleManager and gain_exp in Game_Actor.
B. ) First of all, for "negative levels", all you need to do is change the way that levels are SHOWN to the player. You can use that previously-suggested system where the character starts at Level 50 and can go in either direction to 1 or 99. But wherever the Character Level text is drawn (e.g. draw_actor_level in Window_Base), have it show a number equal to 50 less than the character's actual level instead. So if they're really level 48, it will show up as -2. I belive this will save you a ton of work.
As for the skills, check the level_up and level_down classes in Game_Actor. You'll need to add logic there for resetting the character's skills based on their current level. You could hard-code it (for example, "if character's level is 37 (13 towards Demonic) or below, Learn Skill "Dark Wave", else, Forget Skill "Dark Wave", and do that for every skill for every character), or maybe you can figure out the right way to modify the level/skill checks to add some skills where the values are low enough and others where the levels are high enough.
C) The change_exp method in the Game_Actor class already contains the following code to run the level_up and level_down methods, so I think you can already level down.
level_up while !max_level? && self.exp >= next_level_exp level_down while self.exp < current_level_expD) You actually want the stats (like Strength) to be able to go negative, or you simply want the Levels to be able to go negatives and the stats are adjusted accordingly? If you just want Negative Levels, I explained how to do that in B. If you want Negative Stats, well... "Negative Strength", for example, would be a very weird concept since your players might not know or understand how it factors into battle formulae. But if you really want to do it, here's the method you'll need to change: param_min in Game_BattlerBase. Have it return 0 if MMP, 1 if MHP, and -999 otherwise.
#-------------------------------------------------------------------------- # * Get Reduced Value of Parameter #-------------------------------------------------------------------------- def param_min(param_id) return 0 if param_id == 1 # MMP return 1 endJust be careful in your battle formulae that you never, for example, divide by a stat that might be zero at a given point.
I hope this helps! Your system is specific enough that you'd probably need to commission someone if you wanted the whole thing scripted for you, but if you're getting hung up on any one specific modification that you're trying to make, feel free to ask for some help!