ID:144089
 
In my game, Kingdom Build, there are enemies, one of which is, 'Evil Frog', I tried to create a proc check to see if it's health was less than or equal to 0, and if so, create a head inside of the users inventory. Here's the code:

Boss
name = "Evil Frog"
hp = 500
strength = 60
defense = 36
icon_state="boss"
var/mob/character/Player
proc/Head_Drop()
if(hp <= 0)
new/Items/Frog_Head(usr)
Head_Drop(src)
New()
walkloop
var/walky = rand(1,8)
var/mob/M
for(M as mob in get_step(src,src.dir))
if(!M.client){goto nxt}
for(M as mob in oview(1))
var/damage = rand(1,strength)
sleep(10)
damage -= M.defense
if(damage<=0)
M<<"[src] missed you!"
goto nxt
return
M.hp -= damage
M <<"You are being attacked for [damage] by [src]!"
src.exp += rand(5,10)
src.level_up()
M.death_check(src)
Head_Drop()
goto nxt
nxt
var/mob/P
for(P in oview(1))
if(P.client) {
dir = get_dir(src,P)
sleep(4)
goto walkloop
}
for(P in view())
if(P.client) {
step_to(src,P)
sleep(3)
goto walkloop
}
if(walky == 1) {
step(src,NORTH)
sleep(10)
goto walkloop
}
if(walky == 2) {
step(src,SOUTH)
sleep(10)
goto walkloop
}
if(walky == 3) {
step(src,EAST)
sleep(10)
goto walkloop
}
if(walky == 4) {
step(src,WEST)
sleep(10)
goto walkloop
}
if(walky == 5) {
step(src,NORTHWEST)
sleep(10)
goto walkloop
}
if(walky == 6) {
step(src,NORTHEAST)
sleep(10)
goto walkloop
}
if(walky == 7) {
step(src,SOUTHWEST)
sleep(10)
goto walkloop
}
if(walky == 8) {
step(src,SOUTHEAST)
sleep(10)
goto walkloop
}

It doesn't work. I've tried killing the frog, which doesn't give you the head, nor does letting him kill you do so.

I didn't create this attack code, my Co-owner did, but he isn't available to help me with it, so I'm making due. Please help me if you can,

Michael
Tell your Co-Owner to read the Dm guide.
Right then. Other the default, we've got some problems here. Let's go over them, m'kay?

        proc/Head_Drop() // pass an arguement here
if(hp <= 0)
new/Items/Frog_Head(usr) // use it here


Well, in here, you are attempting to spawn the creature's head inside (usr), but (usr) wasn't even specified! A better way to go over this would be to pass (usr) through as an arguement, through the procedure.

In here you are attempting to call the procedure, but you can only call it through another function!

Head_Drop(src)



This part is the most disturbing, even though seemingly most working part of the code. Let's break it into two big chunks, shall we?

        New()
walkloop
var/walky = rand(1,8)
var/mob/M
for(M as mob in get_step(src,src.dir))
if(!M.client){goto nxt}
for(M as mob in oview(1))
var/damage = rand(1,strength)
sleep(10)
damage -= M.defense
if(damage<=0)
M<<"[src] missed you!"
goto nxt
return
M.hp -= damage
M <<"You are being attacked for [damage] by [src]!"
src.exp += rand(5,10)
src.level_up()
M.death_check(src)
Head_Drop()
goto nxt
nxt



Here you are executing about 10 different actions at the same time. It may seem effective, but really, it isn't. What I'd personally do is transfer each action to its own procedure, and call them as you deem necessary.
Oh, right, I also noticed you are using the 'goto' operator. Such code is not often liked by the fellow programmers here, and so I'd suggest you get rid of it (using it only when completely necessary).

Well, after that you are attempting to move at a random direction, and return to the first loop. As I specified early, such actions would each belong to their own function, and so returning to the 'walkloop' would most likely be removed as you forward your code. Your method of 'wandering' is also quite uh... deluge. Let's go over a more efficient method, and you could choose afterwards which one you would like to stick with.

var/list/possible_directions = list(NORTH,SOUTH,EAST ... // (assuming all possible routes are here) Here we initialized a list of all \
possible directions in which the frog could go to. We will use \
that later. Note that it is also possible to determine these \
mathematically(using mathematical operators, at least!), what \
could prove more efficient. I won't go through that now.


var/chosen_direction = pick(possible_directions) // picking the correct direction...

step(frog,chosen_direction) // move the frog headin in the chosen direction.


Alternatively, DM's <code>step_rand()</code> would do the same, although it automatically picks from every possible direction, meaning your mob could go in a direction you may not want it to go.
In response to Northern Rabbit
Ok, after looking at what you said, I've made a few adjustments to the code. Just to clarify, should I place this:

walkloop
var/mob/M
for(M as mob in get_step(src,src.dir))
if(!M.client){goto nxt}
for(M as mob in oview(1))
var/damage = rand(1,strength)
sleep(10)
damage -= M.defense
if(damage<=0)
M<<"[src] missed you!"
goto nxt
return
M.hp -= damage
M <<"You are being attacked for [damage] by [src]!"
src.exp += rand(5,10)
src.level_up()
M.death_check(src)
Head_Drop()
goto nxt
nxt
var/mob/P
for(P in oview(1))
if(P.client) {
dir = get_dir(src,P)
sleep(4)
goto walkloop
}
for(P in view())
if(P.client) {
step_to(src,P)
sleep(3)
goto walkloop
}
step_rand(8)

(The segment under the New()) Into a proc and call the proc instead of just using it all?

Sorry if I'm wrong and didn't understand you, I'm doing my best.
In response to Michael3131
Well, it's certainly an improvement. You've missed quite a bit of my instructions, though. Maybe it is better understood in code? Here's how I'd do that:

    proc
GiveHead(mob/who) // an arguement passed
new /obj/froghead(who) // give a /obj/froghead to (who)

Lifecycle()
spawn(10)
Lifecycle()
Wander()
var/mob/target = CheckArea()
if(target) Chase(target)

Wander()
step_rand(src)

CheckArea()
var/mob/target = locate() in oview(src,4) // locate a target you can see 4 tiles around you
return target

Chase(mob/target)
// this is where you track down your target. I'll leave this part blank, \
since I didn't really understand how you wanted to do that browsing through \
your code.


Attack(mob/target)
// ...

New()
. = ..()
spawn(1) Lifecycle()


I wouldn't really count it as working(seeing as how I made it as of late and didn't bother testing, or even re-looking at it. Sorry.), that should give you a basic example of a better method of programming. Notice how I gave each action its own function, and how I made each function work together. If you further program that way, you ought to have less problems, and those that you have would be more easily corrected.
In response to Northern Rabbit
Ok! I believe I've fixed most of the problems, but I've still got a few bugs. I'd appreciate it if you could help me with them. Here's the new proc code:
Frogs/proc
Wander()
step_rand(src)

GiveHead(mob/who) // an arguement passed
new /Items/Frog_Head(who) // give a /obj/froghead to (who)
Lifecycle()
spawn(10)
Lifecycle()
Wander()
var/mob/character/Player = CheckArea()
if(Player) Chase(Player)
CheckArea()
var/mob/target = locate() in oview(src,4) // locate a target you can see 4 tiles around you
return target
Chase(mob/character/Player)
walkloop
var/mob/P
for(P in oview(1))
if(P.client) {
dir = get_dir(src,P)
sleep(4)
goto walkloop
}
for(P in view())
if(P.client) {
step_to(src,P)
sleep(3)
goto walkloop
}
Attack(mob/character/Player)
var/mob/M
for(M as mob in get_step(src,src.dir))
for(M as mob in oview(1))
var/damage = rand(1,strength)
sleep(10)
damage -= M.defense
if(damage<=0)
M<<"[src] missed you!"
return
M.hp -= damage
M <<"You are being attacked for [damage] by [src]!"
src.exp += rand(5,10)
src.level_up()
M.death_check(src)

New()
. = ..()
spawn(1) Lifecycle()

Problem is, I get a few bug reports:

oading KingdomBuild.dme
ENEMIES.dm:144:error:New :duplicate definition (conflicts with built-in proc)
ENEMIES.dm:128:error:Attack :duplicate definition
KingdomBuild.dm:1566:error:Attack :previous definition

KingdomBuild.dmb - 3 errors (double-click on an error to jump to it)

The previous Attack it's talking about is this:
mob
verb/Attack(mob/M in oview(1))
if(!M) return
if(M.isplayer==1) return
var/damage = src.strength - M.defense
if(M.AFK==1)
usr<<"You can't attack AFK people!"
if(usr.canattack==1)
if(M.client)
M.hp -= damage
src <<"You attack [M] for [damage]!"
M <<"You are being attacked for [damage] by [src]!"
src.level_up()
M.death_check(src)
canattack = 0
sleep(10)
canattack = 1
else
M.hp -= damage
src <<"You attack [M] for [damage]!"
M <<"You are being attacked for [damage] by [src]!"
var/random = rand(1,3)
if(random == 1)
src.exp += 4
if(random == 2)
src.exp += 3
if(random == 3)
src.exp ++
src.level_up()
M.death_check(src)
canattack = 0
sleep(10)
canattack = 1

I believe the second Attack code is for mob's attacking verb. I'm not sure, I'll poste more code if need be.

Thanks for all the help so far! =)
In response to Michael3131
Dude, he didn't post that code just for you to copy it - but for learning and demonstration purposes only. He even mentioned it isn't good/working, and it isn't, ESPECIALLY if you just copy it into your existing game.

Also, friggin' post your code between <DM></DM> tags - it produces the code box seen earlier in this topic and makes your code MUCH more readable.