Faith System

DarkprinceVI

Villager
Member
Joined
Aug 27, 2014
Messages
8
Reaction score
1
First Language
English
Primarily Uses
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.
 
Last edited by a moderator:

Ralpf

Veteran
Veteran
Joined
Jun 5, 2014
Messages
590
Reaction score
152
First Language
English
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.
 
Last edited by a moderator:

DarkprinceVI

Villager
Member
Joined
Aug 27, 2014
Messages
8
Reaction score
1
First Language
English
Primarily Uses
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
 

Euphoria

Veteran
Veteran
Joined
Jun 27, 2013
Messages
378
Reaction score
93
First Language
English
Primarily Uses
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.
 
Last edited by a moderator:

Ralpf

Veteran
Veteran
Joined
Jun 5, 2014
Messages
590
Reaction score
152
First Language
English
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 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.
 

whitesphere

Veteran
Veteran
Joined
Mar 14, 2014
Messages
1,688
Reaction score
784
First Language
English
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">

####################################################################
# 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
 
 

DarkprinceVI

Villager
Member
Joined
Aug 27, 2014
Messages
8
Reaction score
1
First Language
English
Primarily Uses
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
 
Last edited by a moderator:

Euphoria

Veteran
Veteran
Joined
Jun 27, 2013
Messages
378
Reaction score
93
First Language
English
Primarily Uses
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.
 

DarkprinceVI

Villager
Member
Joined
Aug 27, 2014
Messages
8
Reaction score
1
First Language
English
Primarily Uses
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
 

whitesphere

Veteran
Veteran
Joined
Mar 14, 2014
Messages
1,688
Reaction score
784
First Language
English
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
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.

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.
 

Wavelength

MSD Strong
Global Mod
Joined
Jul 22, 2014
Messages
5,624
Reaction score
5,104
First Language
English
Primarily Uses
RMVXA
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!
 
Last edited by a moderator:

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

Latest Threads

Latest Posts

Latest Profile Posts

People3_5 and People3_8 added!

so hopefully tomorrow i get to go home from the hospital i've been here for 5 days already and it's driving me mad. I miss my family like crazy but at least I get to use my own toiletries and my own clothes. My mom is coming to visit soon i can't wait to see her cause i miss her the most. :kaojoy:
Couple hours of work. Might use in my game as a secret find or something. Not sure. Fancy though no? :D
Holy stink, where have I been? Well, I started my temporary job this week. So less time to spend on game design... :(
Cartoonier cloud cover that better fits the art style, as well as (slightly) improved blending/fading... fading clouds when there are larger patterns is still somewhat abrupt for some reason.

Forum statistics

Threads
105,868
Messages
1,017,083
Members
137,583
Latest member
write2dgray
Top