ID:1750478
 
(See the best response by Nadrew.)
mob
var
PlayerStats/stats = new

PlayerStats
Health
var
xp = 0
max_xp = 100
value = 100
max_value = 100
bonus = 0

mob
proc
test()
src.stats/Health.value = 0
var/t = src.stats/Health.value
src << t //Just to get rid of warning saying t is not used...src.stats/Health.value


The first line under test() works. The second line, var/t... does not work.

Error:
...Health.value: undefined var

Just a little hint, if you changed the first line from src.stats/Health.value = 0 to src.stats/Health.values = 0 it will tell you that Health.values is an undefined var. Meaning that it is setting values to the variable, but it can't retrieve from it.

Do you think this is a bug?
Best response
The problem is that you're trying to access the contents of /PlayerStats/Health but you're not creating an instance of that type, and the method you're using to access it is outright incorrect. The syntax 'src.stats/Health' isn't pointing at anything, it's simply trying to divide src.stats by Health.value (which doesn't exist). The 'first line' under test() shouldn't be working at all but I imagine the compiler is getting confused.

mob/var/PlayerStats/Health/my_health = new()

my_health.value = 50
src << "Your health is [my_health.value]"


If you want to access it in the method of 'src.stats.Health' you'll need to do something along the lines of

Stat
var
value = 100
// etc etc
Health
Magic

StatHandler
var/Stat
Health/health = new()
Magic/magic = new()

mob
var/StatHandler/stats = new()
verb/test()
src << "Your health is [stats.health.value]"
src << "Your magic is [stats.magic.value]"
Maybe you should leave this stuff to toby, you should focus on making the Art! Get on it!
In response to Nadrew
Nadrew wrote:
.. trying to divide src.stats by Health.value...

LOL... Why I didn't realize, I don't know. But, now... It all makes sense. I guess there really isn't a way to have 1 datum contain all the variables then, huh? Rather than creating multiple variables.
In response to Zasif
Zasif wrote:
Maybe you should leave this stuff to toby, you should focus on making the Art! Get on it!

Says the person who constantly pesters him about trivial programming and just doesn't understand what he's trying to explain to you in the most simplest of manners, even writing the code for you and having me input on what he should send you as well. If you have nothing constructive to say, shutup. What you just said is utterly rude. We both do with equally on our projects.
Stats
var
health = 100
magic = 10
strength = 5

mob
var/Stats/stats = new()
verb/Test()
src << "Your health is [stats.health]"
src << "Your magic is [stats.magic]"
In response to Nadrew
So I can't do away with this then?
            hp = 100
max_hp = 100
hp_bonus = 0

magick = 75
max_magick = 75
magick_bonus = 0


pow = 10
pow_bonus = 0

def = 7
def_bonus = 0

magic_pow = 10
magic_pow_bonus = 0

magic_def = 7
magic_def_bonus = 0

agi = 5
agi_bonus = 0

crit_chance = 10
crit_chance_bonus = 0

crit_scaling = 1.25
crit_scaling_bonus = 0


I guess a datum would make it easier to save though. Because the datum holds all of the variables it seems like a good idea still. Even though there's only 1 difference as opposed to having just plain variables.

I'm mainly trying to make it easier on myself in the longrun to add and remove variables. If I kept the previous method (just regular variables), then I'd have to add the new variables to Save(), Load(), Skills, stat panel, everywhere... Whereas if I used a datum to control them, I could reduce it to just Skills... stat panel.. and other places. Since Save and Load will only need to save the datum I'm guessing.
I'm not sure how your system is set up, but would a list of datums work?
Stat
var
current
max
bonus
New(var/newCurrent,var/newMax,var/newBonus)
current = newCurrent
max = newMax
bonus = newBonus
mob
var
list/Stat/stats = list(
"Health" = new /Stat(100,100,0),
"Magick" = new /Stat(75,75,0)
)
mob/verb/test()
var/Stat/health = src.stats["Health"]
world << "My current health is [health.current]."
mob/verb/iterate()
for(var/name in src.stats)
var/Stat/temp = src.stats[name]
world << "My current [name] is [temp.current]."

This would allow for iteration, so you could access all stats without having to specifically name them. Not sure if this is viable in your case though.
Well, looks like, with Nadrew's help, I came up with a solution to make things a bit easier to manage, save, and manipulate.

mob
attackable
var
level = 1
bonus_xp
StatHandler/stats = new


PlayerStats
var
val = 1 //Set to 1 to avoid dividing by 0 if there are any mistakes in New()
max
bonus = 0
xp = 0
max_xp = 100

Health
New(_val, _max, _bonus)
if(_val)
val = _val

if(_max)
max = _max

if(_bonus)
bonus = _bonus

Magick
New(_val, _max, _bonus)
if(_val)
val = _val

if(_max)
max = _max

if(_bonus)
bonus = _bonus

Power
New(_val, _max, _bonus)
if(_val)
val = _val

if(_max)
max = _max

if(_bonus)
bonus = _bonus

Endurance
New(_val, _max, _bonus)
if(_val)
val = _val

if(_max)
max = _max

if(_bonus)
bonus = _bonus

Magick_Power
New(_val, _max, _bonus)
if(_val)
val = _val

if(_max)
max = _max

if(_bonus)
bonus = _bonus

Magick_Defence
New(_val, _max, _bonus)
if(_val)
val = _val

if(_max)
max = _max

if(_bonus)
bonus = _bonus

Agility
New(_val, _max, _bonus)
if(_val)
val = _val

if(_max)
max = _max

if(_bonus)
bonus = _bonus

Crit_Chance
New(_val, _max, _bonus)
if(_val)
val = _val

if(_max)
max = _max

if(_bonus)
bonus = _bonus

Crit_Scaling
New(_val, _max, _bonus)
if(_val)
val = _val

if(_max)
max = _max

if(_bonus)
bonus = _bonus

StatHandler
var/PlayerStats
Health/hp = new
Magick/magick = new
Power/pow = new
Endurance/def = new
Magick_Power/magic_pow = new
Magick_Defence/magic_def = new
Agility/agi = new
Crit_Chance/crit_chance = new
Crit_Scaling/crit_scaling = new


Edit:

I'm not going to try this unless someone knows about it, but... what if I called New() ..() instead for each sub datum and the parent New() was under PlayerStats instead, saving a crap load of lines and would result in me having to only change it in one place. I was originally going to do this... But not sure if it would work.

Edit #2:

Or hell.. Just do away with the ..() and have New() under PlayerStats. They should read from it regardless shouldn't they?
In response to Mightymo
Mightymo wrote:
I'm not sure how your system is set up, but would a list of datums work?
> Stat
> var
> current
> max
> bonus
> New(var/newCurrent,var/newMax,var/newBonus)
> current = newCurrent
> max = newMax
> bonus = newBonus
> mob
> var
> list/Stat/stats = list(
> "Health" = new /Stat(100,100,0),
> "Magick" = new /Stat(75,75,0)
> )
> mob/verb/test()
> var/Stat/health = src.stats["Health"]
> world << "My current health is [health.current]."
> mob/verb/iterate()
> for(var/name in src.stats)
> var/Stat/temp = src.stats[name]
> world << "My current [name] is [temp.current]."
>

This would allow for iteration, so you could access all stats without having to specifically name them. Not sure if this is viable in your case though.

Good method. But, I'm striving for efficiency and the laziest way possible in the long run. Having to typecast stats everytime would be a hassle. Which is why I was avoiding some ways of doing this to begin with... I just don't want to have to type too much because of poor planning. Having variables set when they're never used is inefficient because that uses RAM. This also goes for having that variable accessible by things that will never use it, or never need it. Having a list is just an eyesore, even though it works. And, it's problematic to add to (takes up time and effort). Factoring all these things in, Nadrew's method kind of works best. It's the closest I think I'll get to what I was imagining to do.
Alright, but you can still better your implementation; since all of your datums are exactly the same, you could reduce it down to one datum, and just have each variable be an instance of that datum. Just use the new from the children to the parent and use that instead.
StatHandler
var/PlayerStats
hp = new
magick = new
...

This would be no different than your current implementation, but would be more compact.
In response to Mightymo
PlayerStats
var
val = 1 //Set to 1 to avoid dividing by 0 if there are any mistakes in New()
max
bonus = 0
xp = 0
max_xp = 100

New(_val, _max, _bonus)
if(_val)
val = _val

if(_max)
max = _max

if(_bonus)
bonus = _bonus

StatHandler
var/PlayerStats
hp = new(_val = 100, _max = 100)
magick = new
pow = new
def = new
magic_pow = new
magic_def = new
agi = new
crit_chance = new
crit_scaling = new


A lot more compact... Yes.
Also, you should be able to iterate through a StatHandler using the vars list, which would allow you to iterate through the datum so that any process that wants to look at all stats can go through the list of stats without you having to name each individual stat. Unfortunately requires the same typecasting as above, but you would only have to do it in procs that iterate.
In response to Mightymo
Mightymo wrote:
Also, you should be able to iterate through a StatHandler using the vars list, which would allow you to iterate through the datum so that any process that wants to look at all stats can go through the list of stats without you having to name each individual stat. Unfortunately requires the same typecasting as above, but you would only have to do it in procs that iterate.

I'll keep that in mind. We'll probably have use for using the vars list again since we've already used it twice throughout the whole project. Saves a lot of time. Thanks.