Index | FAQ | Search | Memberlist | Usergroups | Profile | Log in to check your private messages | Log in | Register

Custom light entities (for use in level design) Goto page 1, 2 Next

| Inside3d Forums Forum Index -> QuakeC Programming

View previous topic :: View next topic
Author | Message
--- | ---
Zylyx_ Joined: 05 Dec 2007 Posts: 111 Location: scotland, uk |

Posted: Thu Dec 25, 2008 7:58 pm Post subject: Custom light entities (for use in level design) |

Hey. I'm doing some quakec programming, and starting from scratch (based on the Scratch Tutorials). I want to add lighting to my level. Now, what I really want todo is to allow the level designer to have access to only 2 light entities, one called "light", and the other “light_model”, because I don’t see the point of having 7 different lighting types, when they could all be controlled by a single entity with different attributes, or keys.
I have written a module called lights.qc, and this is what I have in it:

Code:
float START_OFF = 1; // Light on/off spawnflag void LightSetup (); void() light = //light entity { LightSetup(); //setup light attributes
}
void() light_model = //not implemented in fgd yet
{
Precache_Set(self.model, self); //set specific model needed
//consider making this a sprite?
makestatic(self); //entity is static and cannot be deleted
}
void LightSetup () =
{
if (self.style < 32) //if light style cycles is less then 32, return
{
return;
}
if (self.spawnflags & START_OFF)
{
lightstyle(self.style, "a"); //if light starts off, keep it off
}
else
{
lightstyle(self.style, "m"); //i flight starts on, keep it on
}
}
void LightStyles_setup () =
{
float light_style; //custom light style
string value; //custom light cycle value
lightstyle(light_style, value);
}

and I call it in main.qc, which has all the base non-player specific subroutines

Code:
//spawn the level (world object) void worldspawn () = { precaches(); LightStyles_setup();
}

So basically I want to add two light entities to be used when making a level, one for dealing with normal lights, and the other for dealing with lights which require a model (or a sprite).
So instead of the level designer having to go with the already pre-defined light styles, he/she could make her own light style, and give it a light cycle value of something like "mmmkfkffkejwjsdkkk", give it a custom color and so on.
Now what I would like to know is whether or not I'm doing this correctly, because when I tired this with my test map, I placed and entity and gave it two new keys, one called "light_style" (value 1), and the other called "value" (value fkfdfkdkmmmmmyy). I also added a "color" key, but this is handled by hmap2.exe, used for creating the .dlit files for colored lights.
Unfortunately, when I run my map, all I get is a dim blue light, and I can’t see any changing light cycles. So I don’t know if I'm doing this the right way, or if there is a better way todo this, or if I'm just being stupid. I would appreciate any sort of guidance on this matter.
Side note: I'm using WorldCraft 3.3 along with the DarkPlaces Quake client.
Thanx!
_________________
....noodle...

Back to top |

Wazat Joined: 15 Oct 2004 Posts: 732 Location: Middle 'o the desert, USA |

Posted: Fri Dec 26, 2008 6:43 pm Post subject: |

Your LightStyles_setup function does not appear to be written correctly, as it declares two local variables (not parameters or a loop) and uses them without initializing them to anything. Probably just remove that function entirely, unless it's needed to serve some other purpose (like setting up some pregenerated light styles for mappers to just grab).
Also, if you're setting a light's lightstyle in the map editor, you'll need a corresponding .string in the code to receive that value. In defs.qc (or wherever you set your .float's and .string's), add something like this:
.string value; // used for custom light styles on lights
or this:
.string lightstyle; // used for custom light styles on lights
Even better than adding a new .string, re-use one of the existing .strings so you're not using up more memory. For example, use netname instead of value. For simplicity, I'm assuming you're using .value since that's what you originally went for. Just keep variable re-use in mind. You have a special luxury since you're writing quake from scratch.
The next thing you need to do is change LightSetup() so that it checks if a light has a .value:

Code:
void LightSetup () = { if (self.style < 32) //if light style cycles is less then 32, return { return;
}
if (self.spawnflags & START_OFF)
{
lightstyle(self.style, "a"); //if light starts off, keep it off
}
else
{
//if light starts on
if(self.value == "")
{
lightstyle(self.style, "m"); // start on at normal level with nothing special happening
}
else
{
lightstyle(self.style, self.value); // start on with a custom style
}
}
}

The next step is to edit your trigger code so that it checks for custom light styles as well when it turns a light back on. It will use the same code as above, using "m" if there is no .value set.
I cannot remember any other steps, but other coders here should be able to point them out.
The last thing that comes to mind is your entity in your map. It should have two values:
"classname" "light"
"style" "<some unique number>"
"value" "<some alphabetical string for the light style"
This is important. The code lightstyle(self.style, "m"); doesn't set the style for an entity, it sets a style for a slot, an index. self.style is a number (integer index as far as I know) that the string gets tied to. All lights with the same .style will have the same light style. Let's say you have 3 lights in your map:
"classname" "light"
"style" "41"
"value" "abcdefghijklmnopqrstuvwxyzaaaa"
"classname" "light"
"style" "41"
"value" "aaaaaaazzzzzzzaaaaaaaaaaaaazzzzzzzzzzzzzzzzzz"
"classname" "light"
"value" "abcdefghijklmnopqrstuvwxyzaaaa"
The first two lights have the same style set, so whichever one gets set up last will overwrite the first one's custom style, and they'll both blink the same.
The third light has no style set and thus defaults to 0. This means it will try to set style 0 to its incremental strobe, but your own code will tell it no.
if (self.style < 32)
That code I assume comes from the old light code. If I remember right, 0-32 were preset light styles mappers could use. They would simply give their light a "style" number and it would use the preset. I recommend you support this, btw, for the sake of supporting old and new maps alike that will be using the preset. There's plenty of style numbers above 32 (up to 64 I think) for you to use for custom styles.
I hope that helps!
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.

Back to top |

Zylyx_ Joined: 05 Dec 2007 Posts: 111 Location: scotland, uk |

Posted: Sat Dec 27, 2008 12:55 am Post subject: |

cool thanx! I'll try implementing that over the weekend and get back to you on how it goes. _________________ ....noodle...

Back to top |

mh Joined: 12 Jan 2008 Posts: 910 |

Posted: Sat Dec 27, 2008 1:16 am Post subject: |

Nice idea But...! I do wish people wouldn't advocate reuse of existing strings in an unexpected manner. From an engine coder perspective, it's one of those little minefields that can turn what seems like a simple job into a mess of mod-compatibility hacks.
Even from a pure QC perspective, I can see another mod that depends on netname being set to identify something about the entity, and this would totally throw it if someone tried to integrate the two.
If it walks like a duck and quacks like a duck, but is actually a custom light entity, it's a recipe for trouble, eh?
Just my 2 cents...
_________________
DirectQ Engine - New release 1.8.666a, 9th August 2010
MHQuake Blog (General)
Direct3D 8 Quake Engines

Back to top |

Wazat Joined: 15 Oct 2004 Posts: 732 Location: Middle 'o the desert, USA |

Posted: Sat Dec 27, 2008 4:47 am Post subject: |

I can see where you're coming from. I had always thought that the extra bytes per entity were a big problem, but there's also that issue. I'll keep that in mind in my future modding. In fact, it's kind of permission to make my future code and map entities more intuitive.
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.

Back to top |

Urre Joined: 05 Nov 2004 Posts: 1073 Location: Sweden |

Posted: Sat Dec 27, 2008 2:07 pm Post subject: |

Wazat: I'd say that, nowadays, bothering with a byte here or there is quite counterproductive. It used to make sense when RAM was more limited. Networking also shouldn't be a big problem, because only values which can be seen are sent, and they're only sent when they change. In any case I vote for cleaner and readable code over saving a few bytes here and there.
Also, the entire community should stop fearing spawning entities. If an engine doesn't support more than 512 entities nowadays, one shouldn't use it.
_________________
Look out for Twigboy

Back to top |

MeTcHsteekle Joined: 15 May 2008 Posts: 397 Location: its a secret |

Posted: Sat Dec 27, 2008 2:44 pm Post subject: |

Urre wrote:
If an engine doesn't support more than 512 entities nowadays, one shouldn't use it.

how do i make engine support >512 ent's?
_________________
bah

Back to top |

Zylyx_ Joined: 05 Dec 2007 Posts: 111 Location: scotland, uk |

Posted: Sun Dec 28, 2008 4:40 pm Post subject: |

Ok, so I got around to implementing the new code, and I understand it well. I declared a new field in defs.qc, called .string lightvalue, which takes in the lightcycle pattern value. The other .style value is already defined. The code compiles well without any problems.
I did a small test map to try all of this out, and I placed 3 lights in the map. However, when I run my compiled map in DarkPlaces, all I see is my three colored lights, but they are all static and are not flickering or anything like that.
These are the values for the light entities I have placed in my map:
classname "light"
style "0"
lightvalue "hhmhmhmhmhhoof"
classname "light"
style "1"
lightvalue "amjamjamjamj"
classname "light"
style "2"
lightvalue "amamam"
I'm not usre why it's not working. Seeing as they all have individual styles, is it perhaps that the lightvalue needs to be a certain format (e.g. limited amount of characters or letter types).
Please let me know what you think. In the meantime, I'll be fiddling with my code & level entities .
thnx.
_________________
....noodle...

Back to top |

Wazat Joined: 15 Oct 2004 Posts: 732 Location: Middle 'o the desert, USA |

Posted: Sun Dec 28, 2008 7:16 pm Post subject: |

It may be something simple -- post your code again and we'll take a look. _________________ When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.

Back to top |

Zylyx_ Joined: 05 Dec 2007 Posts: 111 Location: scotland, uk |

Posted: Sun Dec 28, 2008 7:41 pm Post subject: |

yeah, k. Lights.qc

Code:
//FIRE LINE code //LIGHTS.QC //Light entity managment code (includes code to setup different light entity types) float START_OFF = 1; // Light on/off spawnflag void LightSetup ();
//The main light funcion in the game. This fucntion is used for setting up custom lights in all levels
void() light =
{
LightSetup();
}
//Same as above, but can load custom sprites and models that can represent the light source
void() light_model =
{
Precache_Set(self.model, self);
makestatic(self);
}
void LightSetup () =
{
if (self.style < 32) //if lightstyle cycles is less then 32, return
{
return;
}
if (self.spawnflags & START_OFF) //if light gets spawned switched off, keep it switched off
{
lightstyle (self.style, "a");
}
else
{
if (self.lightvalue == " ")
{
lightstyle (self.style, "m"); //if light spawns on, keep it on
}
else
{
lightstyle (self.style, self.lightvalue); //else, if user has set custom light style and light cycle, use that instead
}
}
}

and thsi si where it get's called in main.qc

Code:
void main () = {}; //Used for testing progs? //spawn the level (world object) void worldspawn () = { precaches();
LightSetup();
}

The code seems to be fine, but it might just be a problem with how WorldCraft deals with entities.
_________________
....noodle...

Back to top |

Wazat Joined: 15 Oct 2004 Posts: 732 Location: Middle 'o the desert, USA |

Posted: Sun Dec 28, 2008 11:22 pm Post subject: |

Three problems that I'm seeing: 1) I don't think you should be calling LightSetup from worldspawn(). At that point self will be world, which should not be a light source with a style set most likely. You're already calling LightSetup from the light spawn function, so every light will set itself up. I may be wrong though -- maybe some lighting programs will let you have a style on worldspawn that affects the ambient light in the whole level (though that'd make me nauseous personally).
2) if (self.lightvalue == " ") probably won't work, since a blank string is "" not " ". You probably don't want the space in there.
3) The reason your styles are not taking effect at all is because your map entities have styles 1-3, which your code will ignore. Remember, those are for preset light styles which your code doesn't set yet. Your code won't let lights with style < 32 set a custom light style.
If you want your lights to be able to set their own custom light styles, then their "style" field should be set to 32, 33, 34, 35, etc.
I hope that helps.
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.

Back to top |

Zylyx_ Joined: 05 Dec 2007 Posts: 111 Location: scotland, uk |

Posted: Mon Dec 29, 2008 12:37 am Post subject: |

That works great! Thank you very much for your help. I'm a bit of a n00b when it comes to QuakeC programming (I come from a C++ programming background). Sometimes I get sloppy at coding and make stupid mistakes, but the code makes a lot more sense now.
Now, onto implementing the custom ambient sounds!
_________________
....noodle...

Back to top |

Wazat Joined: 15 Oct 2004 Posts: 732 Location: Middle 'o the desert, USA |

Posted: Mon Dec 29, 2008 1:49 am Post subject: |

Have fun! _________________ When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.

Back to top |

Baker Joined: 14 Mar 2006 Posts: 1538 |

Posted: Tue Dec 30, 2008 9:02 am Post subject: |

MeTcHsteekle wrote:

Urre wrote:
If an engine doesn't support more than 512 entities nowadays, one shouldn't use it.

how do i make engine support >512 ent's?

Find MAX_EDICTS in the code. GLQuake had this at 600.
Most moderately modified Quake engines have upped it to 2048.

Back to top |

goldenboy Joined: 05 Sep 2008 Posts: 310 Location: Kiel |

Posted: Thu Jan 01, 2009 9:05 am Post subject: |

You might want to bump MAX_STATIC_ENTITIES and a couple others of that type, too. You'll also want the packet overflow fix.

Back to top |

Display posts from previous:

| Inside3d Forums Forum Index -> QuakeC Programming | All times are GMT Goto page 1, 2 Next
Page 1 of 2

Jump to:

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Powered by phpBB © 2004 phpBB Group