ID:144401
 
Code:
mob
proc
beam()
var/obj/F = new/obj/beamhead //From now on, F is the beam.
F.dir = src.dir
F.loc = src.loc
while(F) //While the beam still hasn't hit anything...
var/L[]
var/obj/H = new/obj/beamtail
H.dir = F.dir
L=L+H
sleep(2) //Set the speed of beam here
H.loc = F.loc
step(F,F.dir)
var/turf/T = F.loc //For the turfs T has travelled over
if(T.density) //If the turf is dense
del F
for(H in L)
del H
break
else
for(var/mob/M as mob in T)
if(M==src) continue
world<<"[M] has been hit by [src]"
del F
for(H in L) del H
break


Problem description:
Lately, ive just been doing a bunch of mini things to practice up, and my latest thing is trying to get lists to work. I've never been comfortable with lists because they never seem to do what I want. Anyways, I was trying to use it in a beam proc. The problem is, when I check L (the list) for H (the tail of the beam), L doesn't seem to contain anything. I think it has something to do with my method of adding H to L, but i'm not sure. Help please, oh, and please, PLEASE don't just give me the code. If there is a way you can explain just what i'm doing wrong with adding/deleting or something else, that would be great. Examples are ok, just don't give me the working example. Thanks.

Sorry, I'm too tired and not in the mood to closely inspect all your code, (I was gonna not reply at all, but you were too cool with the "explain please don't just give code so I copy&paste" and won me over) but I found a problem where you suspected.
L=L+H


That's not how to add an item(s) to a list. What you are doing, is resetting the L var with the value of (L+H) (and trying to calculate it will probably make a runtime error, a type mismatch one). Lists aren't handled the same as numbers etc. If L was a number, then
L=L+1
would naturally be the same as
L += 1


This isn't the case with lists - you can't add an item to a list the way you've done - you have to use the += operator. This is because the += operator has SPECIAL meaning when used with lists (and the = operator doesn't have it). Using += is equivalent of using the list.Add() procedure - and in fact, it may very well be a shortcut to just that.

Also, I gather you're not actually trying to add 2 items to the list, since if you are then it's stupid since you're adding the list itself to it. Well, you should of understood the right way to add items to the list by now.

So here is the bad line fixed:
L += H
//OR
L.Add(H) //you must typecast the L var as of type /list, though

Adding multiple items to a list:
L += item_1
L += item_2
L += item_3
//OR (special usage)
L += list(item_1,item_2,item_3) //each item in the list is individually added, rather than the list itself


I direct you to read the following topics in the DM Reference:
-list operators
-Add proc
-list proc
-list
And just for general knowledge:
-list associations

Note *as suggsted above), lists are actual object datums, (of type /list) and when defining lists, you should always typecast them as /list (otherwise, you can't use list procs).
In response to Kaioken
Ok, thanks. Ok, I've read all the references, my code is sadly still not working, and i'm getting fustrated. I keep rereading the lists chapter, and it's not coming to me. The plot of the code is to add all tail beams to the list so I can just delete them all at once.
In response to Avren
Can anyone help me out?
In response to Avren
Avren wrote:
Can anyone help me out?

Sure.
The truth is, there are more things you did badly in the first initial code, that don't even have to do with lists. I'll explain them all this time - I'm less tired today, so I'll check all your code this time. >.>

Note: For people to actually help you, you need to post your [now updated] code. ;P
In response to Kaioken
Ok, what I have now isn't much different than before, but here it is:
mob
proc
beam()
var/obj/F = new/obj/beamhead //From now on, F is the beam.
F.dir = src.dir
F.loc = src.loc
while(F) //While the beam still hasn't hit anything...
var/obj/H = new/obj/beamtail
var/list/L[]
H.dir = F.dir
L+=H
sleep(2) //Set the speed of beam here
H.loc = F.loc
step(F,F.dir)
var/turf/T = F.loc //For the turfs T has travelled over
if(T.density) //If the turf is dense
del F
for(H in L)
del H
break
else
for(var/mob/M as mob in T)
if(M==src) continue
world<<"[M] has been hit by [src]"
del F
for(H in L) del H
break
In response to Avren
Avren wrote:
var/list/L[]
Should be:
var/list/L[0]

I just glanced over it but, that is one of the problems I spotted. Also, personally - I'd advise just making the trails appear in obj/beamhead/Move().

EX:
obj
beamhead
var/mob/owner
New(loc,dir,mob/own)
src.owner=own
//initialize your beam moving/seeking crap here
return ..()
Move(new_loc,new_dir)
if(isturf(new_loc))
var/turf/T=new_loc
if(T.density)
return 0
var/obj/beamtail/Tail=new(src.loc,src.dir)
Tail.owner=src
return ..(new_loc,new_dir)
beamtail
var/obj/beamhead/owner
In response to Teh Governator
To me, that's erm, sorta confusing. The goal is to work with lists because I don't have the slightest idea how to work with them. Secondly, I seriously don't know how the whole ownership var works, and lastly, I don't know why you need arguments in the Click... Neither do I know what the argument is in the New for. :(

Not making me very happy with all these new confusing things.


I know what the code does, but about 90% I have never seen the likes of before. What about the "if(isturf(blah))" thing? That makes no sence, if isturf?? Never have I ever heard of that. Wouldn't it be "if(istype(T))"? If there is any possible way you can explain where you got all these crazy arguments and return ..(blah), and the other stuff, that would be wonderful! Now i'm lost.. again :(
In response to Teh Governator
Teh Governator wrote:
Avren wrote:
var/list/L[]
Should be:
var/list/L[0]

No. L[] also works.

I just glanced over it but, that is one of the problems I spotted. Also, personally - I'd advise just making the trails appear in obj/beamhead/Move().

Yes, thats the flaws in his code and why it won't work regardless of lists.

Avren, if you don't understand some arguments etc in procs... look them up in the reference!

I'll have a detailed explanation post sometime later for you.
In response to Kaioken
Kaioken wrote:
Teh Governator wrote:
Avren wrote:
var/list/L[]
Should be:
var/list/L[0]

No. L[] also works.


I'm a little rusty, but i'm pretty sure you need var/list/L[0] to actually initialize the list.
In response to Justin B
Straight from the DM Reference entry for 'list':
var/L[] // same as var/list/L: list reference

Putting 0 in the brackets is pretty silly. You're explicitly saying "initialize to 0 items". Which is of course "don't initialize at all".
Also. doing var/list/L[] is kind of a waste, because that shortcut is so you can straight do var/L[], as seen in the above quoted example from the reference.
In response to Kaioken
Kaioken wrote:
Straight from the DM Reference entry for 'list':
var/L[] // same as var/list/L: list reference

Putting 0 in the brackets is pretty silly. You're explicitly saying "initialize to 0 items". Which is of course "don't initialize at all".
Also. doing var/list/L[] is kind of a waste, because that shortcut is so you can straight do var/L[], as seen in the above quoted example from the reference.

mob
verb
Test()
var/L[]
L+="Test"
for(var/search in L)
world << search
mob
verb
Test1()
var/L[0]
L+="Test"
for(var/search in L)
world << search


As I said, i'm a little rusty, but you need to initialize the list in order to change it.
In response to Kaioken
Kaioken wrote:
Straight from the DM Reference entry for 'list':
var/L[] // same as var/list/L: list reference

Putting 0 in the brackets is pretty silly. You're explicitly saying "initialize to 0 items". Which is of course "don't initialize at all".
Also. doing var/list/L[] is kind of a waste, because that shortcut is so you can straight do var/L[], as seen in the above quoted example from the reference.

var/list/l
var/j[]
mob/verb/test(){
.=..();
l.Add("lol", "wtf?");
}

mob/verb/test2(){
.=..();
j.Add("lol", "wtf?");
}

I assure you these both don't work.
In response to Noid
I can assure you too. The problem isn't with the typecasting. Both your posted code and Avren's define a list var, but you're not setting it to a value - its null.

You're typecasting the 2 vars as of type /list, but you're not initializing them, their value is null - using the brackets is equivalent to initalizing as /list. So when you try to use the += operator on them, it will give a runtime error
j[] DOES typecast the var as a list. Again though, it isn't set to a new /list object, it's null.

Correctly doing it would be:
var/list/l = new //equals var/list/l = list()
var/j[] = list() //dunno if 'new' will accept this as a tyepcasted var, so use this to make sure.


Now, I dunno if doing j[0] will automatically initialize it to a list object - though it's pretty stupid and illogical if it does. Also, the reference entry doesn't state that usage; I posted my previous post by it only, as I personally dunno and define my lists with the first approach - it's a bit more readable.
EDIT: OK, so apparently for some reason the BYOND developers decided that [0] will initialize the var to a new list object, for some reason, albeit it weird and undocumented. :P
In response to Avren
Avren wrote:
Ok, what I have now isn't much different than before, but here it is:

First I'll comment the code, then explain how it should be done.

mob
> proc
> beam() //(0) define a new proc for all /mob types named 'beam'
> var/obj/F = new/obj/beamhead //(1) create a new object of type /obj/beamhead and assign it to a var named F, and typecasted as of type /obj.
> F.dir = src.dir //set the beam's dir to the mob's dir
> F.loc = src.loc //(2) force the beam to move to the mob's turf.
> while(F) //While the beam exists, not while it hasn't hit something!
//This executes the indented statement, then checks if F exists, then if so executes it again, and repeats
> var/obj/H = new/obj/beamtail //(1) create a new object of type /obj/beamtail and assign it to var H, typecasted as of type /obj .
> var/list/L[] //define a new list, typecasted as a list. this is ok, same as doing var/list/L = new or var/list/L = list()
> H.dir = F.dir //set the trail's dir to the beam's dir
> L+=H
> sleep(2) //Set the delay of the beam's moves here. The higher the number, the slower the beam!
> H.loc = F.loc //(3)Force move the trail to F's turf
> step(F,F.dir) //(4) move F (trail) in F's direction (which is also the beam (H)'s direction)
> var/turf/T = F.loc //Create a new var typecasted as turf and assign it F's location (turf). This is pretty useless and can be skipped, just use F.loc in its place.
> if(T.density) //(5)If the turf is dense //this part is highly flawed. in this case you used step() which uses the movement system, and the movement system shouldn't of moved F to a dense turf at all anyway.
> del F
> for(H in L) //if this part doesn't work (I'm not currently sure), you need to do: 'for(var/a in L) del a'
> del H
> break //no need to do a manual break, since we made the while() condition 'while F is valid'/'while F exists' - the loop would still automatically end without this line
> else
> for(var/mob/M as mob in T)
> if(M==src) continue
> world<<"[M] has been hit by [src]"
> del F
> for(H in L) del H //see previous similar line
> break //see previous similar line


1)You should really just typecast it as the same exact object type. If you typecast it as of type /obj/beamhead is still inherits /obj variables of course, so this is no problem. So you should do:
var/obj/beamhead/F = new /obj/beamhead()

DM also has a convienent shortcut to get rid of the redundancy - you can make the above code line shorter like this:
var/obj/beamhead/F = new ()


2,3) Setting atom.loc directly is forcing movement without executing the movement system. However, in THIS specific case, it should be fine though - you only just created the object, and it had loc=null, you initalized its location with the right value.
Doing this (forcing loc var) also means custom overrided movement stuff you have like overriding Enter() won't get run - but usually for a projectile, you won't care.
The 2nd time you do this, you're making it move with a movement proc afterwards...that doesn't make sense at all.

4) This is moving the object via the movement system. Using that step() equals to using: F.Move(get_step(F,F.dir)).
That is good usage and you should generally ALWAYS move things this way.
Note that I don't think you even wanna move trials around here...unless its not really a trail but a 2-tile beam or something.

5) As stated in the comment, that won't work. Use BYOND's movement system procs. Look up atom/movable/Move(). That proc checks if movement is allowed, based on Exit() and Enter() procs. If movement is blocked by a dense object then it will eventually the Bump() proc - look it up, thats where you need to do stuff when the beam hits something. Also read this: http://bwicki.byond.com/ByondBwicki.dmb?HowToBump
This crap page may also help. >.> Shows moving procs sequence.
http://bwicki.byond.com/ByondBwicki.dmb?MovementBasics


0) This may be annoying, but you should scrap the existing code and re-write, pretty much. Look at the way beam demos are done (BUT demos are unfortunately often crappily coded - so don't imitate them closely, just see how stuff is done). Also, I suggest not having a mob/beam() proc. Have a beam system with child types of /obj/beam having vars such as speed, damage, and procs required for shooting and using. That allows for more flexibillity.

<s>I'll edit this post with a quick example of a beam system shortly.</s>
In response to Kaioken
Ended up making a demo. :o
http://developer.byond.com/hub/Kaioken/ProjectileDemo

Please learn from it, see how stuff is done, don't directly use it in your game.
In response to Kaioken
Thanks a bundle, I'll probably reread all this info after school. Thanks. Oh, would you mind going over what the arguments are in New? Like New(_loc,mob/_owner) //What is the / for, and since when do you need arguments in procs like New?
In response to Avren
Avren wrote:
Oh, would you mind going over what the arguments are in New? Like New(_loc,mob/_owner) //What is the / for, and since when do you need arguments in procs like New?

You can override New() to do certain things when an object is created. For instance, this code:

obj/portal
var/atom/target

...


var/obj/portal/O=new(src.loc)
O.target=locate(5,5,3) //location to teleport to


By overriding New(), you can do this:
obj/portal
var/atom/target
New(loc,atom/target)
.=..() //perform anything else you redefine later
if(target) src.target=target

...

new/obj/portal(src.loc,locate(5,5,3))


The result is cleaner code. Normally you'd create the object and then specify the target. In this case, it's irrelevant: you can create portals all you want and specify the target directly from New().

In this case, the atom/target bit typecasts target to be /atom. This means that you can safely access any variables and are sure that both /area, /turf, /obj and /mob's inherit these variables. In this case we're not actually doing anything with this bit of information but it's good to know it's there for when you modify that code in the future. It also shows you what the target variable is supposed to be: an atom to teleport whatever enters the portal to.
Using an adapted version of this code, you can make a one-way portal like so:

obj/portal
var/atom/target
New(loc,atom/target,duration=300)
.=..() //perform anything else you redefine later
if(target) src.target=target
if(duration) spawn(duration) del src
//TODO: use Bump() or something to have the portal teleport people

...

new/obj/portal(src.loc,locate(5,5,3),500)
new/obj/portal(locate(5,5,3),null,500)


You can enter through the portal you just created to goto the other. But you can't enter the other, or you will die.

What arguments you use in New() (or any proc) are your choice entirely.
In response to Android Data
Yeah, well explained Android. :)
Just to clarify, because it may be obvious to us but not to him - the arguments specified in new() are passed on to New().
This is the order at which stuff happens:
1. new type(args) is called.
2. object of 'type' is created
(3.) This is a special step, for atomic objects only. If the first parameter (loc) is specified, the object is created at that loc. So actual placement occures between new() and New(), but not in either of them.
4. that object's New() proc is called with 'args'.
Avren wrote:
Thanks a bundle, I'll probably reread all this info after school. Thanks. Oh, would you mind going over what the arguments are in New? Like New(_loc,mob/_owner) //What is the / for, and since when do you need arguments in procs like New?


First of all, when overriding procedures, you can add extra, custom arguments. As simple as that. Note that when calling a procedure, you can supply an INFINITE amount of procedures (except some built-in exceptions like the step(),walk() series procs), even more than those defined in the proc itself (like you can have countless args in procs like ismob()). To see how that comes in use, look up the "args" var in the reference.
Second, as implied above, I added a custom arg (as implied above, loc is a default special arg) to New(), and I supplied it in new(), which passed it on to the former.
This is frequently used for easy, quick object variable initialization.

I appended an underscore to the argument variable names, so there is no confusion (to both human reader AND compiler), because the object has it's own variable named "loc" and "owner", so I needed to make them different names.
Actually since I used explicitly used "src.owner" instead of shortening with "owner", the compiler should had no problem. I still decided to do it though.

Argument variable declarations are the exact same as normal, only that you can omit the beginning "var/".
The "/" I have is typecasting; it means the "_owner" variable is of type "/mob".

There's a bit of stuff I missed in the demo, I think, (no bugs, but "features" I forgot) so I'll update it sometime later (I'll edit this post and the hub page when I'm done).
In response to Android Data
obj/portal
var/atom/target
New(loc,atom/target,duration=300)
.=..() //perform anything else you redefine later
if(target) src.target=target
if(duration) spawn(duration) del src
//TODO: use Bump() or something to have the portal teleport people

...

new/obj/portal(src.loc,locate(5,5,3),500)
new/obj/portal(locate(5,5,3),null,500)


--This code was by Android Data

Just curious from what Kaioken said about the new being passed on to New. Just to confirm, but does that work like this? :
New(loc,atom/target,duration=300)
//Ok, starting with src.loc in the bottom code; src.loc. So in the upper code, loc is src.locate from the bottom code?
//and so fourth with all the arguments? That would mean the duration for the portal would be 500?
//If that is true, how does atom/target work with "locate(5,5,3)"?
//And in this case, since no one said who src was in the bottom code, does that make src locate
//to 5,5,3? Or does it make it locate to itself?
new/obj/portal(src.loc,locate(5,5,3),500)

Finally, is it the same thing with this?:
new/obj/portal(locate(5,5,3),null,500)
The final question is, what is null... Oh, hehe, it just came to me.. You don't have anything to set for that! It would be good if you could confirm though. Thanks.
Page: 1 2