ID:1411933
 
(See the best response by MisterPerson.)
So, for a long time I've noticed areas existed in the Dream Maker, but never really understood the full capabilities of their functionality in the game development. The F1 help tool left me asking a lot of questions, and I was wondering if anyone could give me the run down on some interesting uses for them, as well as answering a few questions I have specifically. Usually I'd go about finding out this kind of thing with trial and error on a blank project, but the help left me with so many questions that I thought it'd be better to just ask! :D

First question is about the fact that the help says that one area object is created for each defined type, but you can create multiple copies of rooms by calling with "null" as the argument in null. How does one create one of these 'new' versions of an area during run-time so that the new copy is added to? For example, maybe I want it so that when I create a "Tower" lets say for an aura effect I want to create an area on each tile up to 3 spaces away from it. How would I accomplish creating a 'new' area and applying all these tiles to that new area instead of the basic area for the area type? I need to have a different area for each copy of the tower so that I can read every object within its contents for applying any triggering effects related to the aura of effect from the tower, but not to influence any other instances of the tower around the map. The F1 help does not give any instruction related to how these 'new rooms' function or if adding to a 'new room' is even possible.

Second Question, is there anything special that happens if you call a new area of the same type on the same x/y/z location multiple times? Or is it just ignored?

Third Question, for each time you call 'new' on an area, does it call "New()" on that area, or is "New()" only called when a type of area is created for the first time, or is it done at start-time when these objects supposedly are created for each area type?

I know this is a lot to ask at once, but areas really have very poor instruction of their capabilities, so thank you for any help you can offer towards any of these questions, or any other interesting uses.
Felix Rose wrote:
First question is about the fact that the help says that one area object is created for each defined type, but you can create multiple copies of rooms by calling with "null" as the argument in null. How does one create one of these 'new' versions of an area during run-time so that the new copy is added to? For example, maybe I want it so that when I create a "Tower" lets say for an aura effect I want to create an area on each tile up to 3 spaces away from it. How would I accomplish creating a 'new' area and applying all these tiles to that new area instead of the basic area for the area type? I need to have a different area for each copy of the tower so that I can read every object within its contents for applying any triggering effects related to the aura of effect from the tower, but not to influence any other instances of the tower around the map. The F1 help does not give any instruction related to how these 'new rooms' function or if adding to a 'new room' is even possible.

From what I understand, any areas of the same type next to each other count as one single area. So, correct me if I'm wrong but if you spawn 3 new areas at run-time, and two of them are touching but the third is not, then the two touching counts as one area and the third is it's own.

Felix Rose wrote:
Second Question, is there anything special that happens if you call a new area of the same type on the same x/y/z location multiple times? Or is it just ignored?

Creating a new area of the same type on the same x,y,z co-ordinates will overwrite the area that was there before.

Felix Rose wrote:
Third Question, for each time you call 'new' on an area, does it call "New()" on that area, or is "New()" only called when a type of area is created for the first time, or is it done at start-time when these objects supposedly are created for each area type?

Every time you create a new atom, New() is called. For example:

obj/Doors
New()
//Code here
src.name="Door"
Door1
New()
//Code here.
if(src.name!="Door")
return ..() //Calls the parent


When you create Door1:
new/obj/Doors/Door1()


It will call New() and then if the name is not Door it will call the parent proc, which sets the name to Door.
In response to Lavitiz
Actually, all areas of the same type are the same area, touching or not.
In response to Kaiochao
Kaiochao wrote:
Actually, all areas of the same type are the same area, touching or not.

Ah, I didn't know this. Good to know :D
With further study into the F1 help on "new" and re-reading some stuff on areas themselves.. my question about what happens if you call more than one object to the same location and I realize my misunderstanding of how "new/area(null)" works with creating rooms... so my only remaining question is simply how new and del function on areas.

Does "New()" get called each time you add to the area object, or is it only called on the initial creation of the area, or both?

What the heck happens with "del(AreaInQuestion)", how does it work? Does it delete all instances of the area across the map? If so would the only way to remove area from a tile be to add a new area of another type on top of its current location?
In response to Felix Rose
Felix Rose wrote:
Does "New()" get called each time you add to the area object, or is it only called on the initial creation of the area, or both?
New should be called with each creation. I think. I don't use areas often.

Felix Rose wrote:
What the heck happens with "del(AreaInQuestion)", how does it work? Does it delete all instances of the area across the map? If so would the only way to remove area from a tile be to add a new area of another type on top of its current location?

Once again, I'm not quite sure. I want to say deleting one area deletes them all. This might have happened to me when I deleted an area of weather tile years ago. I'd need feedback from a more experienced developer though, I don't have time to go check.

If you do happen to delete an area though, it should be replaced with a /area type path though. You can't have no areas on a map.
Areas are pretty terrible simply because you can't stick things in multiple areas. Each turf only has one loc referring to one area.
I don't see why that would be a problem considering areas and turfs are bound to the same grid size regardless of pixel movement and whatnot, so a turf can really only exist in a single area. I can't imagine a situation where it would be of benefit to have the same turf in two areas.
In response to Kaiochao
Kaiochao wrote:
Actually, all areas of the same type are the same area, touching or not.

Unless explicitly instantiated.
Best response
Think of all the cool things you can use areas for. Weep as you can only use one per project if that.

Map loading and unloading, to help with processing without having to loop through a bunch of range()es or view()s. for(var/area/A in loaded_area_list) if(area.players.len == 0) if(area.adjacent_area_players.len == 0) unload(area)
(Entered() and Exited() would of course keep a tally of the player lists.)

Map logic: Things in the same area are presumed close together. Faster to loop through area.contents instead of view() or range(). Useful for mappers because they can plop down the area visually. Pretty much what areas are designed for I suppose.

Lighting areas: See all the good lighting libraries. Areas make this faster than objects. Can't be datums because they have to be displayed.

AI activation/deactivation without having to calculate which mobs to activate/deactivate. Make a bunch of specific areas that when a human enters, calls npcActivate() on every NPC in the area. When all the players leave you just call npcDeactive(). Heck, these could be placed arbitrarily and moved at runtime. Being able to map this visually would be good. To make this useful though it would be best if connections between two areas were in both areas so you can't get a weird effect where an enemy is nearby or even chasing you but since you crossed a deactivation point, his AI shuts off suddenly.

Arbitrary shaped bounds: limited to turf-sized edges if/until areas support bounding boxes. Still there's potential usage here.

Effects: You could handle this with a datum I suppose but a) that kind of defeats the purpose of areas and b) it'd be great to have a visual representation on the map without having to use a clunky object/overlay system. Anyways the idea is area/effect/burning and then you can have a verb like
lightOnFire(mob/M, duration)
var/area/A = locate(/area/effect/burning)
A.contents += M
A.effecting[M] = duration

then have area/effect/burning as the following:

var/list/effecting = list()
process()
for(var/i = 1, t < effecting.len, i++)
var/atom/movable/M = effecting[i]
var/effect_time = effecting[M]
-- code to burn things --
if(effect_time <= 0)
effecting.Remove(M)
contents -= M


Different burn strengths can be totally distinct areas with different icon_states, vars, or even procs entirely.
In response to MisterPerson
MisterPerson wrote:
Areas are pretty terrible simply because you can't stick things in multiple areas. Each turf only has one loc referring to one area.

Yeah areas really are starting to look terrible. It sounds like doing something like this could accomplish anything an area could do and more..

zone
var/list/Contents=list() //Hold a list of turf that are in the zone.
proc
Entered(atom/movable/Obj) //Explain what you want to do when you enter the 'Zone' object's Contents.
Exited(atom/movable/Obj) //Explain what you want to do when you exit the 'Zone' object's Contents.

Add(list/List) //This to add a link a turf to the zone and the zone to the turf.
//The argument is a list so that you can call things like "zone.Add(view(2,zone))" directly.
for(var/turf/Turf in List)
if(!(Turf in Contents))
Contents+=Turf
Turf.Zones+=src
Remove(list/List) //This to properly detatch any turf from the list.
for(var/turf/Turf in List)
if(Turf in Contents)
Contents-=Turf
Turf.Zones-=src
turf
var/list/Zones=list() //This is a list of any zones that this object is connected to.
Entered(atom/movable/Obj)
for(var/zone/z in Zones)
if(Obj in z)
z.Entered(Obj) //Call Entered(Obj) on every zone that does not already contain Obj
Exited(atom/movable/Obj)
for(var/zone/z in Zones)
if(Obj in z)
z.Exited(Obj) //Call Exited(Obj) on every zone that does contain Obj
Map loading and unloading

A single call to block() is reasonably fast

Map logic

Oversized bounding boxes are probably better for this, but incur a small memory overhead.

AI activation/deactivation

True. However, oversized bounding boxes are good for this as well.

Arbitrary shaped bounds

Oversized bounds again, but with geometric functions work just fine.


Areas are best left to region behavior and lighting, really.
In response to Ter13
Wow, I never actually thought of using large sized objects for such things. In fact I only ever really thought about using large sized objects for PCs and NPCs.. this actually just opened up a huge number of possibilities thinking of everything from moving smogs of gas that need to know exactly what are in their contents to apply effect, or to an aura on an object to apply passive benefits to nearby allies in an RPG game.. that's pretty badass thank you for making me think of the possibilities!
In response to Felix Rose
Felix Rose wrote:
Wow, I never actually thought of using large sized objects for such things. In fact I only ever really thought about using large sized objects for PCs and NPCs.. this actually just opened up a huge number of possibilities thinking of everything from moving smogs of gas that need to know exactly what are in their contents to apply effect, or to an aura on an object to apply passive benefits to nearby allies in an RPG game.. that's pretty badass thank you for making me think of the possibilities!

It's somewhat less efficient if they move around a lot, than using range() or bounds() If they are stationary, though, it's extremely efficient.
A lot of handy stuff can be done with areas, but they do have the limitations mentioned already in this thread.

I think that they were originally added to the language to suit its MUD roots. They're mostly intended to bound off "rooms". Or so I've always assumed.

In Murder Mansion, which uses Shadowdarke's "Dynamic Area Lighting" library, I've extended their use to a bit more than what the original library intended, by creating subtypes of the basic "indoor" and "outdoor" areas the library provides, in order to name rooms/areas of the map, and to override Enter/Exit to trigger the proper "inside" vs "outside" sounds and effects.

They're useful for marking off individual areas on the map. Hence the name.