ID:149948
 
I find the . and : operators very confusing... Working with my war game, I am constantly using :. I don't want to, if I can help it, but I'm not exactly sure how to set up my code to like the period. As an example, I have choppers, both light and heavy types. These can also be one of four colors, for each team: red, black, blue and green. I arrange them first by thier color, then by thier type. I use this setup so I can check to see if a player is on a certain team like:
    if(istype(M,/mob/red))

Although, now that I think about it, I could check the mob's team var... heh... *smacks himself* Anyways...

So I have:
mob
red
choppers
icon = 'choppers.dmi'

var
mob/red/chopper_blades/BLADES = new()
mob/red/shadow/SHADOW = new()
FLYING = 0
TRANSIT = 0

verb
flight()
toggle_flight(usr) // defined below as a mob/proc

light
icon_state = "red_light"

heavy
icon_state = "red_bomber"

Choppers also have mobs for thier shadow when they take off, and a mob for thier blades, which both move with the chopper as it travels... ( I would like to make the blades overlays, but I'm not sure if I can change an overlay's icon_state)
            chopper_blades
icon = 'choppers.dmi'
icon_state = "blades_off"
layer = MOB_LAYER + 1

var
SPINNING = 0

shadow
icon = 'choppers.dmi'
icon_state = "shadow"
layer = MOB_LAYER - 1
density = 0

Now this is where all those nasty : come in... the toggle_flight() proc:
mob
proc
toggle_flight(var/mob/M as mob)
if(M:TRANSIT) return 0

var
DIRECTION = src.dir

if(M:FLYING == 1)
M:TRANSIT = 1
step(M,SOUTH)
M.dir = DIRECTION
M:SHADOW.loc = M.loc
M:BLADES.loc = M.loc
density = 1
M:FLYING = 0
M:BLADES.icon_state = "medium_blades"
sleep(6)
sight = 0
sleep(6)
M:BLADES.icon_state = "slow_blades"
sleep(9)
M:BLADES.icon_state = "blades_off"
M:BLADES:SPINNING = 0
M:TRANSIT = 0
return 0

if(M:FLYING == 0)
M:TRANSIT = 1
M:BLADES.icon_state = "slow_blades"
sleep(9)
M:BLADES.icon_state = "medium_blades"
sleep(12)
M:BLADES.icon_state = "fast_blades"
density = 0
step(M,NORTH)
sight = 30
M.dir = DIRECTION
M:BLADES.loc = src.loc
M:BLADES:SPINNING = 1
M:FLYING = 1
M:TRANSIT = 0
return 1


Now I know that's a horendous way of doing things, but it works.... (poor excuse for bad code) What am I doing wrong here, that : is so prevelant? I am thouroughly baffled... Comments, critisizm, heckling and fun-poking all welcome! (Also, any other general flaws you might notice in my code I would like to know about) Thanx!

~X :-\
To my knowlage, the way you are handling the operators in those procs is just fine... as long as var/mob/M is a chopper! If it's a mob that does not have those vars, errors will be generated. By using the colon operator, you are telling the computer that you know for sure that the variables you are reading and writing to are present. Try changing var/mob/M to var/mob/choppers/M or something of the sort. I beleive that that will clear up your problems, because it will tell the compiler that the mob will be a chopper and not just some ordinary mob. Failing that, add a check like
if(!istype(M,/mob/chopper))
world.log << "ERROR: [M] is not a chopper!"
return
to make sure the proc crashes if the mob type is not correct. I hope I was of help to you!

-Lord of Water
In response to Lord of Water
Well, there are no errors when I compile, or at runtime. The code there works perfectly, and I don't see how it would ever be called except by a chopper. I was just wondering how I would change the code, so I wouldn't have to use : so much, if at all... that was my origional question....

~X
In response to Xooxer
Heh, I've never used : in my life...
Xooxer wrote:
These can also be one of four colors, for each team: red, black, blue and green.

What? No grey team? ;)

I arrange them first by thier color, then by thier type. I use this setup so I can check to see if a player is on a certain team like:
>     if(istype(M,/mob/red))
>

Although, now that I think about it, I could check the mob's team var... heh... *smacks himself* Anyways...

This is part of the reason you find yourself using the : operator so much. It also means that for each unit type, you have to define it four times, once for each team. If you make a change in blue choppers, you'll have to redo red, green, and black as well. Keeping parallel code is a massive headache. Turn back before it's too late!

I'd map it out like

mob
// everything common to all mobs
tank
// everything common to all tanks
chopper
// everything common to all choppers
light
// light chopper specific code
heavy
// heavy chopper specific code

and use a variable to divy them up into teams. (Maybe even go further and make tanks, choppers, and whatever else a subdivision of /mob/combat_unit, since you have non-combat mobs like rotors and shadows. That way you only have to look for combat_units in your targeting and/or damage code.)


Now this is where all those nasty : come in... the toggle_flight() proc:

mob
proc
toggle_flight(var/mob/M as mob)

If you had all choppers in one type path, you could change the argument to accept only chopper mobs

mob/proc/toggle_flight(var/mob<font color=#ffff99>/chopper</font>/M as mob)

and then use the . operator with M throughout the proc. it would know M is a chopper and that it has those values.

Or you could change it to a chopper proc and leave out the argument.

mob<font color=#ffff99>/chopper</font>/proc/toggle_flight()

and use "src." where you were using "M:". You would have to change your proc calls from "toggle_flight(ChopperMob)" to "ChopperMob.toggle_flight()".


With your current object tree, the : operator is the most reasonable way to consolidate code for all the chopper mobs into one proc.


Also, I recommend using objs instead of mobs for rotors and shadows unless you intend for a client to occupy them. It won't have a major impact, it's just a personal preference of mine.

Best of luck. :)
I see a problem right here:
proc
toggle_flight(var/mob/M as mob)

Two things: The var keyword doesn't belong there, and as mob is redundant. This could well be preventing the compiler from recognizing that M is a mob type.

Beyond that, you need to make vars like FLYING and TRANSIT available to all mobs, or rearrange your mobs so that some common subclass uses them.

Lummox JR
In response to Xooxer

and I don't see how it would ever be called except by a chopper.

This is a well-known developer pitfall: assuming that everything you create will be used in the fashion you intended. Murphy's oft-misconstrued law actually boiled down to the axiom that if there is any number of right ways and even one wrong way to do something, humans would choose the wrong way, regardless of labelling, instructions, or the intent of the creator. (In typical fashion, his criticism of human nature was "sound-bited" down to a trite expression of bad luck and cruel fate.)

In short, you, the developer might never put your creation into a situation where a proc designed to run with mobX will rull with mobY... after all, you know when and where the proc is supposed to be run.

In other words, you might never try to put the Purple Jewel into the Yellow Idol, because you know that it goes in the Purple Idol. A little foresight can help prevent some of these situations... you may be correct, it may be impossible to call this proc for anything but a chopper. But as your code grows, you'll have to spend more and more time and effort "herding" procs and verbs, putting in extraneous and often redundant checks to make sure that only the right type of mob can trigger a particular trigger, and so on and so forth... and in doing this, you'll be hampered by your own knowledge of how the game is supposed to work.

Properly typing your mobs can help reduce the amount of code you need to get things done, the amount of vigilance and rigor you have to use in "defending" against inappropriate proc-calls, and all in all makes your code more manageable. As I've said before, it isn't that : is bad... but that situations which force its use reveal a weakness in your code.