ID:169741
 
I need an example of how to code Curse seal,okay here I go. I want an NPC to bite someone and they have a 1/30 chance of getting bitten and their level has to be passed 260 or the NPC won't even attempt to bite the player.

After the player has been bitten they have a 1/10 of chance of getting cursed,after the player gets passed all that they get the seal.Once you get the seal your nin,gen and tai will double,How would I do all that XD.
Broly103 wrote:
I need an example of how to code Curse seal,okay here I go. I want an NPC to bite someone and they have a 1/30 chance of getting bitten and their level has to be passed 260 or the NPC won't even attempt to bite the player.

After the player has bitten they have a 1/10 of chance of getting cursed

Up to there, I was able to follow you:

mob
player
var/level = 1
npc
proc/bite(mob/player/victim)
//If the victim is non-existant or not really a /mob/player,
//then end the proc right here
if(!(victim && istype(victim))) return
if(victim.level > 260 && prob(3))
//victim gets bitten
if(prob(10))
//victim gets cursed


after the player gets passed all that they get the seal.Once you get the seal your nin,gen and tai will double,How would I do all that XD.

I didn't quite understand what you were talking about there.

On the forums, it's very important to be clear, specific, and informative. Your excessive use of pronouns made it really hard to understand you, and the run-on sentences didn't really help either =P.

If you need more help than that which I've already provided, then please rephrase your request. It's particularly unclear as to what a "seal" is (tell us the type path!), and when they should get it. Should the victim get the seal if and only if he's been cursed? Should the victim recieve it if and only if he's been bitten, but not cursed? Should the victim recieve it regardless of what happens? Please specify.
In response to Wizkidd0123
Wizkidd0123 wrote:
Broly103 wrote:
I need an example of how to code Curse seal,okay here I go. I want an NPC to bite someone and they have a 1/30 chance of getting bitten and their level has to be passed 260 or the NPC won't even attempt to bite the player.

After the player has bitten they have a 1/10 of chance of getting cursed

Up to there, I was able to follow you:

> mob
> player
> var/level = 1
> npc
> proc/bite(mob/player/victim)
> //If the victim is non-existant or not really a /mob/player,
> //then end the proc right here
> if(!(victim && istype(victim))) return
> if(victim.level > 260 && prob(3))
> //victim gets bitten
> if(prob(10))
> //victim gets cursed
>

after the player gets passed all that they get the seal.Once you get the seal your nin,gen and tai will double,How would I do all that XD.

I didn't quite understand what you were talking about there.

On the forums, it's very important to be clear, specific, and informative. Your excessive use of pronouns made it really hard to understand you, and the run-on sentences didn't really help either =P.

If you need more help than that which I've already provided, then please rephrase your request. It's particularly unclear as to what a "seal" is (tell us the type path!), and when they should get it. Should the victim get the seal if and only if he's been cursed? Should the victim recieve it if and only if he's been bitten, but not cursed? Should the victim recieve it regardless of what happens? Please specify.

I mean after you get the seal, when you activate it your ninjutsu,genjutsu and Taijutsu will double. Thats what i meant at the end.
In response to Broly103
Broly103 wrote:
I mean after you get the seal, when you activate it your ninjutsu,genjutsu and Taijutsu will double. Thats what i meant at the end.

What is the type path of "the seal"? When should the victim recieve a seal? Should he recieve it when he's been bitten, but not cursed, or when he's been both bitten and cursed?
In response to Wizkidd0123
Wizkidd0123 wrote:
Broly103 wrote:
I mean after you get the seal, when you activate it your ninjutsu,genjutsu and Taijutsu will double. Thats what i meant at the end.

What is the type path of "the seal"? When should the victim recieve a seal? Should he recieve it when he's been bitten, but not cursed, or when he's been both bitten and cursed?

He has to be bitten and cursed in order to get the seal.
In response to Broly103
Wizz: If you still don't get it, go ask a naruto fan ( These names remind me of names my friend ( a naruto fan ) spoke ) .
In response to Broly103
Broly103 wrote:
He has to be bitten and cursed in order to get the seal.

That answers one question of mine, but you still haven't told me the type path of your seal object. "mob/player" is an example of a type path, if you didn't answer because you don't know what a type path is.

Anyway, assuming that the type path of the seal is /obj/seal, then you would do something like this:

mob
player
var/level = 1
npc
proc/bite(mob/player/victim)
//If the victim is non-existant or not really a /mob/player,
//then end the proc right here
if(!(victim && istype(victim))) return
if(victim.level > 260 && prob(3))
//victim gets bitten
if(prob(10))
//victim gets cursed
victim.contents += new/obj/seal()
victim.ninjutsu *= 2
victim.genjutsu *= 2
victim.taijutsu *= 2

</dm>
In response to Wizkidd0123
Wizkidd0123 wrote:
Broly103 wrote:
He has to be bitten and cursed in order to get the seal.

That answers one question of mine, but you still haven't told me the type path of your seal object. "mob/player" is an example of a type path, if you didn't answer because you don't know what a type path is.

Anyway, assuming that the type path of the seal is /obj/seal, then you would do something like this:

> mob
> player
> var/level = 1
> npc
> proc/bite(mob/player/victim)
> //If the victim is non-existant or not really a /mob/player,
> //then end the proc right here
> if(!(victim && istype(victim))) return
> if(victim.level > 260 && prob(3))
> //victim gets bitten
> if(prob(10))
> //victim gets cursed
> victim.contents += new/obj/seal()
> victim.ninjutsu *= 2
> victim.genjutsu *= 2
> victim.taijutsu *= 2
>

</dm>

Yeah I did not know the path,yeah but the player gets the seal then after he can deactivate and activate the seal any time he wants.But it will drain 200 stamina every 30 seconds until deactivated.
In response to Broly103
Broly103 wrote:
Yeah I did not know the path,yeah but the player gets the seal then after he can deactivate and activate the seal any time he wants.But it will drain 200 stamina every 30 seconds until deactivated.

Well, if I understand correctly, then I think that you're looking for something like this:

mob/player
var/list/drain_vars
proc/drain(drain_var,loss,loop_time)
set background = 1
//initialize drain_vars if it isn't already there
if(!src.drain_vars) src.drain_vars=list()
src.drain_vars["[drain_var]"] = loss
while(src.drain_vars["[drain_var]"])
if(src.vars["[drain_var]"] - loss >= 0)
src.vars["[drain_var]"] -= loss
else if(src.vars["[drain_var]"])
src.vars["[drain_var]"] = 0
sleep(loop_time)
//If drain_vars is empty, then get rid of it
if(!src.drain_vars.len) src.drain_vars = null

obj/seal
verb
activate_seal()
set src in usr
spawn() usr.drain("stamina",200,300)

deactivate_seal()
set src in usr
usr.drain_vars["stamina"] = 0
In response to Wizkidd0123
Wizkidd0123 wrote:
Broly103 wrote:
Yeah I did not know the path,yeah but the player gets the seal then after he can deactivate and activate the seal any time he wants.But it will drain 200 stamina every 30 seconds until deactivated.

Well, if I understand correctly, then I think that you're looking for something like this:

> mob/player
> var/list/drain_vars
> proc/drain(drain_var,loss,loop_time)
> set background = 1
> //initialize drain_vars if it isn't already there
> if(!src.drain_vars) src.drain_vars=list()
> src.drain_vars["[drain_var]"] = loss
> while(src.drain_vars["[drain_var]"])
> if(src.vars["[drain_var]"] - loss >= 0)
> src.vars["[drain_var]"] -= loss
> else if(src.vars["[drain_var]"])
> src.vars["[drain_var]"] = 0
> sleep(loop_time)
> //If drain_vars is empty, then get rid of it
> if(!src.drain_vars.len) src.drain_vars = null
>
> obj/seal
> verb
> activate_seal()
> set src in usr
> spawn() usr.drain("stamina",200,300)
>
> deactivate_seal()
> set src in usr
> usr.drain_vars["stamina"] = 0
>

I keep getting this:
loading File.dme
jutsus.dm:181:error:usr.drain_vars:undefined var
jutsus.dm:177:error:src.drain:undefined proc
also to make this a learning experience,I'm going to study the code till I know what everything does.
In response to Broly103
Broly103 wrote:
I keep getting this:
loading File.dme
jutsus.dm:181:error:usr.drain_vars:undefined var
jutsus.dm:177:error:src.drain:undefined proc

My fault! I forgot to type cast (not to mention defining /mob/player/stamina!). Fixed:

mob/player
var
stamina = 0
list/drain_vars

proc/drain(drain_var,loss,loop_time)
set background = 1
//initialize drain_vars if it isn't already there
if(!src.drain_vars) src.drain_vars=list()
src.drain_vars["[drain_var]"] = loss
while(src.drain_vars["[drain_var]"])
if(src.vars["[drain_var]"] - loss >= 0)
src.vars["[drain_var]"] -= loss
else if(src.vars["[drain_var]"])
src.vars["[drain_var]"] = 0
sleep(loop_time)
//If drain_vars is empty, then get rid of it
if(!src.drain_vars.len) src.drain_vars = null

obj/seal
verb
activate_seal()
set src in usr
var/mob/player/P = usr
spawn() P.drain("stamina",200,300)
usr << "You activate the seal.\
Until the seal is deactivated,\
your stamina will decrease by 200 every 30 seconds."


deactivate_seal()
set src in usr
var/mob/player/P = usr
P.drain_vars["stamina"] = 0
usr << "You deactivate the seal.\
You feel your stamina stabilize again."


The above snippet assumes two things:
  1. You're using a /mob/player type for all player mobs, as opposed to just using /mob. I would actually recommend using a type for your player mobs, if you already aren't anyway.
  2. Non-player mobs will never have any status effect on them that involves draining a certain statistic.

The second assumption is a pretty big one, and probably isn't true. If you're planning on a "poison" status effect, for example, you probably want NPCs to have access to drain(). Therefore, if the second assumption is false, you should use this one:

mob
var
stamina = 0
list/drain_vars

proc/drain(drain_var,loss,loop_time)
set background = 1
//initialize drain_vars if it isn't already there
if(!src.drain_vars) src.drain_vars=list()
src.drain_vars["[drain_var]"] = loss
while(src.drain_vars["[drain_var]"])
if(src.vars["[drain_var]"] - loss >= 0)
src.vars["[drain_var]"] -= loss
else if(src.vars["[drain_var]"])
src.vars["[drain_var]"] = 0
sleep(loop_time)
//If drain_vars is empty, then get rid of it
if(!src.drain_vars.len) src.drain_vars = null

obj/seal
verb
activate_seal()
set src in usr
spawn() usr.drain("stamina",200,300)
usr << "You activate the seal.\
Until the seal is deactivated,\
your stamina will decrease by 200 every 30 seconds."


deactivate_seal()
set src in usr
usr.drain_vars["stamina"] = 0
usr << "You deactivate the seal.\
You feel your stamina stabilize again."


also to make this a learning experience,I'm going to study the code till I know what everything does.

Good! =)

In the code, I make use of a pre-defined associative list called atom.vars, whch contains all of an atoms variables in the format, variable_name == value. You can read about associative lists in chapter 10 of the DM Guide, and in a great article by Lummox JR.
In response to Wizkidd0123
Wizkidd0123 wrote:
Broly103 wrote:
I keep getting this:
loading File.dme
jutsus.dm:181:error:usr.drain_vars:undefined var
jutsus.dm:177:error:src.drain:undefined proc

My fault! I forgot to type cast (not to mention defining /mob/player/stamina!). Fixed:

> mob/player
> var
> stamina = 0
> list/drain_vars
>
> proc/drain(drain_var,loss,loop_time)
> set background = 1
> //initialize drain_vars if it isn't already there
> if(!src.drain_vars) src.drain_vars=list()
> src.drain_vars["[drain_var]"] = loss
> while(src.drain_vars["[drain_var]"])
> if(src.vars["[drain_var]"] - loss >= 0)
> src.vars["[drain_var]"] -= loss
> else if(src.vars["[drain_var]"])
> src.vars["[drain_var]"] = 0
> sleep(loop_time)
> //If drain_vars is empty, then get rid of it
> if(!src.drain_vars.len) src.drain_vars = null
>
> obj/seal
> verb
> activate_seal()
> set src in usr
> var/mob/player/P = usr
> spawn() P.drain("stamina",200,300)
> usr << "You activate the seal.\
> Until the seal is deactivated,\
> your stamina will decrease by 200 every 30 seconds."

>
> deactivate_seal()
> set src in usr
> var/mob/player/P = usr
> P.drain_vars["stamina"] = 0
> usr << "You deactivate the seal.\
> You feel your stamina stabilize again."

>

The above snippet assumes two things:
  1. You're using a /mob/player type for all player mobs, as opposed to just using /mob. I would actually recommend using a type for your player mobs, if you already aren't anyway.
  2. Non-player mobs will never have any status effect on them that involves draining a certain statistic.

The second assumption is a pretty big one, and probably isn't true. If you're planning on a "poison" status effect, for example, you probably want NPCs to have access to drain(). Therefore, if the second assumption is false, you should use this one:

> mob
> var
> stamina = 0
> list/drain_vars
>
> proc/drain(drain_var,loss,loop_time)
> set background = 1
> //initialize drain_vars if it isn't already there
> if(!src.drain_vars) src.drain_vars=list()
> src.drain_vars["[drain_var]"] = loss
> while(src.drain_vars["[drain_var]"])
> if(src.vars["[drain_var]"] - loss >= 0)
> src.vars["[drain_var]"] -= loss
> else if(src.vars["[drain_var]"])
> src.vars["[drain_var]"] = 0
> sleep(loop_time)
> //If drain_vars is empty, then get rid of it
> if(!src.drain_vars.len) src.drain_vars = null
>
> obj/seal
> verb
> activate_seal()
> set src in usr
> spawn() usr.drain("stamina",200,300)
> usr << "You activate the seal.\
> Until the seal is deactivated,\
> your stamina will decrease by 200 every 30 seconds."

>
> deactivate_seal()
> set src in usr
> usr.drain_vars["stamina"] = 0
> usr << "You deactivate the seal.\
> You feel your stamina stabilize again."

>

also to make this a learning experience,I'm going to study the code till I know what everything does.

Good! =)

In the code, I make use of a pre-defined associative list called atom.vars, whch contains all of an atoms variables in the format, variable_name == value. You can read about associative lists in chapter 10 of the DM Guide, and in a great article by Lummox JR.

Thanks again wizz.
Edit: I was reading the dm guide chapter 10, I don't get a thing he is doing :(.
In response to Broly103
The only part I do not understand is, this part.
mob/player
var/list/drain_vars
proc/drain(drain_var,loss,loop_time)
set background = 1
//initialize drain_vars if it isn't already there
if(!src.drain_vars) src.drain_vars=list()
src.drain_vars["[drain_var]"] = loss
while(src.drain_vars["[drain_var]"])
if(src.vars["[drain_var]"] - loss >= 0)
src.vars["[drain_var]"] -= loss
else if(src.vars["[drain_var]"])
src.vars["[drain_var]"] = 0
sleep(loop_time)
//If drain_vars is empty, then get rid of it
if(!src.drain_vars.len) src.drain_vars = null
In response to Broly103
It's not really possible to explain that snippet to you unless you understand associative lists. Please try reading the two sources I gave you earlier in the thread. If, in one of the sources, there's anything that you don't understand, I'll try to explain it to you! =)
In response to Wizkidd0123
Looking at this code now I do see a couple of minor problems. The biggest is that when a drain_var is reset, the value is never actually removed from the drain_vars list, so that list will never be deleted because it will never be empty once it's created.

Another minor issue is that it isn't possible to cause two drains simultaneously without screwing up the stats, nor can one of them be stopped while the other continues.

Savefiles are also an issue. Because the proc is the only thing keeping track of timing, it'll never be possible to restart the drain after a character is reloaded.

Because a drain effect is likely to be temporary and will probably only be used in limited ways, my suggestion would be a datum. Actually, a linked list or a heap would do nicely.

stat_effect
var/varname
var/maxvarname
var/change
var/delay
var/nexttime = 0
var/stat_effect/next

// set to a true value when finished
var/done

New(mob/M, V, C, D)
if(M) // M will be null when loaded from a savefile
next = M.stateffects
M.stateffects = src
varname = V
if("max[V]" in M.vars) maxvarname = "max[V]"
change = C
delay = D
nexttime = world.time + delay
spawn(delay) M.StatEffects()

// this proc needs to know which stat_effect in the list precedes it
// so it can remove itself from the list if need be
proc/Action(mob/M, stat_effect/prev)
if(done)
if(!prev) M.stateffects = next
else prev.next = next
next = null
return 0
if(nexttime && nexttime < world.time)
return nexttime - world.time
nexttime = world.time + delay
if(maxvarname)
M.vars[varname] = max(0, min(M.vars[maxvarname], M.vars[varname]+change))
else
M.vars[varname] = max(0, M.vars[varname]+change)
return delay

Read()
..()
nexttime += world.time
Write(savefile/F)
..()
F["nexttime"] << (nexttime-world.time)

mob
var/stat_effect/stateffects
var/tmp/effectloopid = 0

// call this when loaded if stateffects var is not null
// it is also called any time a datum is created new
proc/StatEffects()
var/loopid = ++effectloopid
while(stateffects && loopid == effectloopid)
var/sleeptime=0, t
var/stat_effect{S; prev}
for({S=stateffects; prev=null}, S, {prev=S; S=S.next})
t = S.Action(src, prev)
if(!sleeptime || t<sleeptime) sleeptime=t
if(!sleeptime) sleeptime = 1
sleep(sleeptime)

proc/EndStatEffect(V, C, D)
for(var/stat_effect/S=stateffects, S, S=S.next)
if(S.varname == V && S.change == C && S.delay == D)
S.done = 1
return S


The above code is pretty complicated, particularly with that loopid thing which needs some explanation. Basically the StatEffects() proc knows it's going to be called more than once, because if a new /stat_effect is added to the chain it might need to be processed before the last sleep() is finished. Therefore, loopid keeps track of whether this instance of the proc is the most up-to-date; if it doesn't match effectloopid, the proc should stop running because somewhere another instance of StatEffects() is already on the case.

For this code, the curse seal would create new/stat_effect(player, "stamina",-200,300). To end that drain, you'd call player.EndStatEffect("stamina",-200,300).

Lummox JR
In response to Lummox JR
Heh -- I'd call "minor problems" a bit of an understatement. Thank you for fixing that, Lummox!

And Broly, I'm sorry for the bad snippet -- especially if it confused you. I'll make sure to check my work more carefully next time!