ID:2255502
 
(See the best response by Ter13.)
Code:
mob
proc
Save() // This is the proc that saves the player
// if(Savable)
if(onlogin)
return
if(key)
if(!src.loc)
return
if(src.loc==locate(37,239,28))
return
var/savefile/F=new("Save/[ckey]")
F["x"]<<x
F["y"]<<y
F["z"]<<z
F["Player Log"]<<PlayerLog
Write(F)
AutoSave()
Save()
spawn(rand(30,100))
AutoSave()
Load()
if(fexists("Save/[ckey]"))
var/savefile/F=new("Save/[ckey]")
Read(F)
F["x"]>>x
F["y"]>>y
F["z"]>>z
F["Player Log"]>>PlayerLog
loc = locate(x,y,z)
icon_state=""
pixel_y=0
pixel_x=0
see_in_dark=3
overlays-='AFK.dmi'
overlays-='SpeakBubble.dmi'
src.hud = new(src)
src.interface = new(src)
onlogin=0


Problem description:

My game was built with a save proc that i'm now learning isn't the most practical. This is what i have on it.


The problem is that after designing the game i discovered my skills aren't being saved on the character and i've been told it's because i didn't use a code similar to this...

client
proc
SaveMob()
var/char_ckey = ckey(mob.name)
F["players/[ckey]/[char_ckey]"] << mob

I've been told that because it's a client process and a mob save it actually saves everything including the skills which would solve my problem, furthermore since i also use an autosave system but im not sure how true this is.

My question is basically am i on the right track? Is it the fact that my save process is under a mob instead of client proc ?? Could i fix everything by switching that or is too much already reliant upon it?

If so are there any other easier ways to add the saving of abilities to my coding?
Please use <d m></d m>...
In response to Dubious Game Studios
Dubious Game Studios wrote:
Please use <d m></d m>...

Gotcha.
In response to LiquidWhip
Also, since indentation is important to the language, you should make sure that the code you post has the original indentation. It's next to meaningless otherwise.

Just using "Write()" instead of "F << mob" isn't enough to make it so your abilities aren't saved. How are abilities referenced by the player?
Here is a push of the coding for abilities here
https://puu.sh/we2NK/5606eab10e.png

and this is a push preview of skill learning rather than having an admin give the verb

https://puu.sh/we36H/829e83e603.png
In response to LiquidWhip
LiquidWhip wrote:
Here is a push of the coding for abilities here
https://puu.sh/we2NK/5606eab10e.png

and this is a push preview of skill learning rather than having an admin give the verb

https://puu.sh/we36H/829e83e603.png

Yeah, I'm not going to read screenshots. poast coad in dm tags please
for some reason i cant get it to post with proper indentation on here so i'll wait for someone who doesn't mind reading it from the screenshot
In response to LiquidWhip
???

If you copy and paste right from DM I think it changes the tabs to spaces because of web formatting, but it should still "look" correct.
Alright this is a code of a new skill im using.

mob/skills/verb/Bio_Extract()
set category="Abilities"
set name="Bio Extract"
if(!grabbee)
for(var/mob/M in get_step(usr,dir))
return
else
for(var/mob/M in get_step(usr,dir))
grabbee=M
view()<<"[usr] is absorbing [M]'s Bio Extract!"
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()
sleep(350)
if(!grabbee)
return
M.liftlb-=M.liftlb/20
M.health-=M.health/10
usr.liftlb+=M.liftlb/20
usr.health+=M.health/10
if(M.health<=1000)
M.Death()



A side qustion i have regarding this skill. Is there a way that i can designate a mob on the SAME tile as me rather than using

for(var/mob/M in get_step(usr,dir))


The problem with this skill it doesn't specify a grabbed target due to the fact that once grabbed they go from the Get_Step to the tile directly on you.

and of course i still need to know how to save abilities.
Oh, goodness. Uh... where to even start. OK.

First of all, any time you're repeating code this much it should be a red flag. There is never an excuse for this. You need to look up while() and for() loops -- type those phrases into your project, highlight them, and then hit F1 on your keyboard. This will search for those terms in the DM reference. For now (get it?) we'll just try directly applying one of them to your problem here.

A for() loop is a way to cut down on repeated code by only specifying the code (or parts of the code) one time. This keeps you from having the heaping helping of spaghetti that you're serving up here. So, instead of having an attack take away life every x seconds y times you could just write something like...

      for(var/i = 1 to 7)
attacked_mob.health -= damage
if(attacked_mob.health <= 0) attacked_mob.die()
sleep(300)
world << "this won't run until after attacked_mob has been attacked 7 times!"


This code will run 7 times and sleep for 30 seconds between each attack. The code after the for() loop will not run until after the for() loop has finished.

As for your get_step() issue... just compare your location with theirs? I don't see how this is a problem.

Are you currently saving characters? "How to save abilities" is a tall order without you even showing an attempt.
Is it possible to compare the locations using the for()? I need to replace the for(var/mob/M in get_step) with one that will make it work for someone on my same location. Can you show me how that part might be done?

Characters save, but abilities learned or given by admins don't.
You can have two different for() loops with one inside of the other. This is called a nested loop.

       for(var/mob/m in turf)
for(var/i = 1 to 7)
// blah blah blah whatever
world << "this runs after the second for() loop runs!"
world << "this runs after the first for() loop has gone over every mob in turf!"


So this would first look for a mob in turf, then it would loop for 1 to 7, then announce something in the default output pane for all mobs in the world. Then, if there's another mob in that turf, it would run that for() loop 7 times again and then make that same announcement. If there are no more mobs in that turf, then it will make the second announcement.

Of course, you don't have to make a nested loop and from the sound of it you don't want one. So instead we're going to have to set up a way to check for both 1) players in front of us (which we already have) and 2) players on the same tile as us. It seems like you want people on the same tile to be the first to be picked, so we'll make our code prefer those mobs:

    var/mob/m
for(var/mob/m2 in loc)
if(m2 == src) continue
else
m = m2
break
if(!m) for(var/mob/m2 in get_step(src,dir))
m = m2
if(!m) return


In this example, we first define a mob variable but don't actually assign a mob to it. Then we search the contents of loc (the turf our mob is currently standing on) for a mob. If the first mob it finds is our mob, it will continue -- this is a way to stop the current iteration of a for() loop from running code it shouldn't without stopping the entire proc entirely.

After it finds a mob that isn't our mob, it assigns it to the mob variable we defined earlier and calls break. Break is a term a lot like continue, except that it stops the entire loop. It's different from a return call because it doesn't stop the entire procedure or verb from running, just the specific loop that it's called from. We call break here to keep from wasting unnecessary resources -- even if there were another mob in that space, we would only want our players to be able to grab one at a time anyway.

Now in the next part we check to see if m is false. We do this because m may already be true from the last for() loop and since we want to grab mobs on the same turf as us first we don't want to accidentally override that mob. After if(!m) (if m is false) we use another for() loop (the one we already had earlier) and if it finds a mob there we set the first mob it finds to m and then break to keep from doing unnecessary checks.

At the very end we do another check for m... if it doesn't exist, we stop the proc. No need to keep going if there's no mob to damage.

---

There are lots of ways to save techniques and skills and characters and everything else. I really can't help you without having any knowledge of what you're currently trying and why it isn't working.
I hate to be a bother but im confused. I'm not even sure where to place your coding in at. I've never used some of these functions before.

I don't know where to place that coding in along with mine to make it work
Can you show me how the skill would correctly work.

Basically the skill is to absorb someone who is already grabbed and it drains them as long as they're still held.

It leeches their stats and i have to make sure that it's ordered correctly, that's why i worried about it finding me on the turf
I gave you plenty of examples and told you what to read up on in your own time to further understand the material. I purposefully did not write your existing code into my examples; I want you to learn, not copy and paste what I write.
If i could see it done correctly just this one time i'd learn from that and be able to understand it.
You have to understand i did alot of coding [as improper as it may be] if i go scrambling into it trying to figure out how to change it i'll have to erase the entire thing just to try something i don't understand.

There's no point in my going through the current coding with a sledgehammer just to get a ton of errors or a nonworking system. Then i'd be right back here bugging you again and probably pissing you off even more and feeling bad about it lol
Best response
Liquidwhip wrote:
There's no point in my going through the current coding with a sledgehammer

More like a sickle than a hammer. We're trimming, not smashing.

Liquidwhip wrote:
get a ton of errors or a nonworking system.

Each of those errors is a learning opportunity. They point to something that is wrong with your code. You learn more through failure than you do success.

Liquidwhip wrote:
if i go scrambling into it trying to figure out how to change it i'll have to erase the entire thing just to try something i don't understand.

Loops are something you should understand from the off before you go trying to write a game. The patterns are as basic as it gets. This isn't some advanced thing or a preference. It's a basic language feature you need to know.

Liquidwhip wrote:
Then i'd be right back here bugging you again and probably pissing you off even more and feeling bad about it lol

Anyone who is responding to this thread is doing it for the sake of helping others. A lot of us having been doing it for a long time. If it bothers us, we do our best to stay away from the thread/person. The only thing that tends to frustrate people that help out here is generally a defeatist attitude, or a refusal to learn something new.

Your post comes off more as arrogance and stubbornness than it does genuine concern for others. I'd advise changing that ASAP. The faster you accept that others know more than you and are thus a source of knowledge, the faster you'll pick up on what they have to offer. Free help is something you should never turn down. It's a rare luxury.

mob/skills/verb/Bio_Extract()
set category="Abilities"
set name="Bio Extract"
grabbee = locate(/mob) in get_step(usr,dir)
if(grabbee)
var/repeat = 26, drainlift, drainhealth
view() << "[usr] is absorbing [grabbee]'s Bio Extract!"
while(repeat--)
if(!grabbee)
return
grabbee.liftlb -= (drainlift = grabbee.liftlb / 20)
grabbee.health -= (drainhealth = grabbee.health / 10)
usr.liftlb += drainlift
usr.health += drainhealth
if(grabbee.health <= 1000)
grabbee.Death()
sleep(350)


LOOK AT THAT. Look how much prettier it is. Look how much less work it is!

All that repeated code takes time to compile. Don't you want to have your game compile faster so you can more quickly iterate and test?

Don't you want to learn how to use the language better so that you can write better code in the first place?

Basically, what's happening here:

A loop is a code structure that repeats a series of instructions until the condition is no longer true.

In this case, we're setting repeat to a value of 26.

Any value that is not zero is a true condition. This means that 26, 25, 24, 23, 22, 21, 20, ... 1 are all going to satisfy the condition of while, allowing the code inside of that loop to run.

while(repeat--)
//do something


while is a statement.

(repeat--) is the condition associated witht he while statement.

the little block of code under the while //do something is the body of the while.

while translates to: "[While] [condition] is true, do [body]"

the -- operator is probably one you don't recognize. It means: subtract 1 from the value to the left, and return the previous value.

var/x = 4
world << x-- //4
world << x //3
world << x-- //3
world << x //2
world << x-- //2
world << x //1
world << x-- //1
world << x //0


-- also has a second form:

var/x = 4
world << --x //3
world << x //3
world << --x //2
world << x //2
world << --x //1
world << x //1
world << --x //0
world << x //0


These are called post-decrement (x--)
and pre-decrement (--x)

So this while() loop that I wrote:

while(repeat--) is actually repeating the body of the loop 26 times without me having to write the code 26 times in a row like you did.


There are also other kinds of loops:

for(x in list) //runs once for each x in list

for(var/count=1;count<18;count++) //3-clause for loop. translates to:

var/count=1
while(count<18)
//body
count++

for(var/count in 1 to 20) //single clause for loop. iterates count from 1 to 20
for(var/count in 1 to 20 step 2) //dual clause for loop. Iterates count from 1 to 20 counting by 2

do
//body
while(condition) //do while loop. Runs at least one time before encountering the condition


There are also other kinds of loops common in programming, but these are the most common you will be using in DM.
And last post: To get to the heart of your question:

Why things aren't saving.

So, your abilities/skills aren't saving because they are being added as verbs.

This is because you are using a stolen Dragonball Zeta rip source. That save code you posted was wrong when it was written. It's especially, egregiously wrong now.

verbs are not saved as part of a mob, nor should they be.

Fixing this problem is beyond your skill at this time. You are better off starting a project from scratch. Zeta sources are so poorly written to the extreme you couldn't even begin to understand right now at your level of skill. When the time comes that you have accumulated the skill to fix it, you won't want to.

I applaud your enthusiasm for diving right in and attempting to muck with the guts of the game, but I and Two of the other guys in this thread can tell you from experience: It's not worth it.
Page: 1 2