Massassi Forums Logo

This is the static archive of the Massassi Forums. The forums are closed indefinitely. Thanks for all the memories!

You can also download Super Old Archived Message Boards from when Massassi first started.

"View" counts are as of the day the forums were archived, and will no longer increase.

ForumsCog Forum → Trouble with class cogs
Trouble with class cogs
2005-08-10, 11:24 AM #1
A simple task, I thought. Below cog is a class cog for a vase/pot template. It is producing a shatter effect and creates a random powerup when damaged enough. The vase then respawns after a set time.
Now, that works just fine, but the template is a _throwable one, so you can move the vases around. It would now be nice when they could be "respawned" at their original locations, instead of the current ones...
Code:
# Jedi Knight Cog Script
#
# ACTOR_POT.COG
#
# This cog makes a pot explode if damaged enough
# Possibly creates a powerup
# Actually a class COG
#
# 2005 Jedi I
#                   modified by zagibu@gmx.ch
# ========================================================================================

symbols

thing		victim				local

template	exp_tpl=+crate_exp		local
template	powerup0=+dhealthpack		local
template	powerup1=+dbactatank		local
template	powerup2=+dshield		local
template	powerup3=+dbattery		local
template	powerup4=+denergycell		local
template	powerup5=+dpowercell		local
template	powerup6=+dsmbp			local

sound		respawn_snd=Activate01.wav	local

flex		life=40				local
flex		wait_time=30			local
flex		health				local
flex		damage				local
flex		rval				local
flex		geo_mode			local
flex		collide_type			local

message		created
message		damaged
message		timer

end

# ========================================================================================

code

created:
	// Give the victim it's initial health
	SetThingUserData(GetSenderRef(), life);

	Return;

# ........................................................................................

damaged:
	victim = GetSenderRef();
	health = GetThingUserData(victim);
	damage = GetParam(0);

	// Check type of damage and handle impact damage as a special case
	if(GetParam(1) & 0x1)
	{
		// Check if a player has applied impact damage to the victim
		if(GetThingType(GetThingParent(GetSourceRef())) == 10)
			Return;
	}

	// Are we applying enough damage to "kill" the poor thing
	if(damage >= health)
	{
		// Create the explosion template at the damaged thing's position
		CreateThing(exp_tpl, victim);

		// Remove the victim (render it invisible and disable it's collision switch)
		geo_mode = GetThingCurGeoMode(victim);
		SetThingCurGeoMode(victim, 0);
		collide_type = GetCollideType(victim);
		SetCollideType(victim, 0);

		// Start the respawn timer
		SetThingTimer(victim, wait_time);

		// Create a random powerup at the victim's position
		rval = Rand();
		if (rval < 0.15)
		{
			CreateThing(powerup0, victim);
		}
		else if (rval < 0.35)
		{
			CreateThing(powerup1, victim);
		}
		else if (rval < 0.45)
		{
			CreateThing(powerup2, victim);
		}
		else if (rval < 0.46)
		{
			CreateThing(powerup3, victim);
		}
		else if(rval < 0.61)
		{
			CreateThing(powerup4, victim);
		}
		else if(rval < 0.66)
		{
			CreateThing(powerup5, victim);
		}
		else if(rval < 0.67)
		{
			CreateThing(powerup6, victim);
		}
	}
	else
		SetThingUserData(victim, health - damage);

	Return;

# ........................................................................................

timer:
	victim = GetSenderRef();

	// Respawn the victim (render it visible and enable it's collision switch)
	SetThingCurGeoMode(victim, geo_mode);
	SetCollideType(victim, collide_type);

	// Reset the victim's health
	SetThingUserData(victim, life);

	// Play the respawn sound
	PlaySoundThing(respawn_snd, victim, 1, 0, 8, 0x0);
 
	Return;
end

I've tried it with simple variables and heaps, but both seem to be overridden by the next vase's class cog...
"Häb Pfrässe, süsch chlepfts!" - The coolest language in the world (besides Cherokee)
2005-08-10, 12:47 PM #2
If we throw out the force throw Idea is it possible to make them respawn
without getting overridden by the next vase or would that problem still
be present. If it is fixable my making the vases so they don't move and
aren't thrown then We should just do that and add in additional force throw
Items. This may just be to complicated to be worth dealing with.
If curiosity killed the cat then perhaps Curious George killed the cat.
But Cat's do have nine lives so who knows?
2005-08-10, 1:22 PM #3
You could just not make it a class cog at all and use it through JED's cog editor. Remove the local from victim and put it in JED's cog editor and set victim to the pot's thing #. That way, they shouldn't be overwriting eachother. You may have to change all the GetSenderRef() to victim this way, though.


For making it respawn in it's original position:

put this in the created message
Code:
   startcoords = GetThingPos(victim);
   startsector = GetThingSector(victim);


put this in the respawn timer
Code:
   SCREWTHEPYR = '0 0 0';
   victimLvec = GetThingLVec(victim);
   spawndummy = CreateThingAtPos(dummytpl, startsector, startcoords, SCREWTHEPYR);
   TeleportThing(victim, spawndummy);
   if(spawndummy != -1) // If the thing limit is reached and the spawndummy doesn't exist, it will remove something else, like the player
   {
      DestroyThing(spawndummy);
   }
   SetThingLook(victim, victimLvec);


define all the variables and make dummytpl something useless like _decor or whatever.

You may need to change "victim" to GetSenderRef() in some places, but you shouldn't need to if you implement the cog through JED's cog placer
visit my project

"I wonder to myself. Why? Simply why? Why why? Why do I ask why? Why do I need to find out why? Why do I have to ask why as a question? Why is why always used to find out why? Why is the answer to why always why? Why is there no final answer to why? Simply why not? Holy cow, this is pretty deep, meaningful **** I wrote. Glad I wrote it down. Oh man."
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ [slog], Echoman
2005-08-10, 2:04 PM #4
[QUOTE=jedi I]If we throw out the force throw Idea is it possible to make them respawn
without getting overridden by the next vase or would that problem still
be present. If it is fixable my making the vases so they don't move and
aren't thrown then We should just do that and add in additional force throw
Items. This may just be to complicated to be worth dealing with.[/QUOTE]
The cog as posted above should make them respawn where they are, so if they can't be moved, it's fine. But I'll try the level cog again, tomorrow. Thanks for the input so far.
"Häb Pfrässe, süsch chlepfts!" - The coolest language in the world (besides Cherokee)
2005-08-10, 7:45 PM #5
How many vases will be in your level? If you added a startup: to the COG that records the initial location and sector of the vase, then in a respawn: section you create a temporary object at that place and TeleportThing() the vase to the temporary object it'd work but you'd need a seperate isntace of the COG for every vase. So, you could duplicate the cog and name them ACTOR_POT_01.COG, ACTOR_POT_02.COG, ACTOR_POT_03.COG. Each vase would needs its own template too.

QM
2005-08-10, 8:39 PM #6
I don't think it is worth it to have every single vase have it's own level cog
because the whole reason for me wanting the vases to have power ups
and respawn was to make a replacement for stray items i.e. you would have
all the pickups in vases to make it slightly more historically realistic. With the
current situation, I think I would rather just not make them moveable and
use the cog how it is as a class cog. I wouldn't worry too much about it but
if you do manage to get a workable class cog then that would be great.

I also don't want 50 different vase templates and cogs because I would be
putting all of the powerups in vases and that would be annoying and unefficient.
If curiosity killed the cat then perhaps Curious George killed the cat.
But Cat's do have nine lives so who knows?
2005-08-10, 8:39 PM #7
Not sure if this'll work, but it's just an idea:

Create two templates:
The vase
A custom ghost

on the vase, attach a class cog that destroys it after so much damage, like the exploding tanks
on the custom ghost, attach a class cog that creates the vase and captures it, when it's destroyed set a timer to create another vase, capture it, and so on.

Then just place the ghost where you want the vase to appear.
2005-08-11, 8:52 AM #8
Why not use a method similar to ProdigyOddigy's? I don't think his will work exactly in a class cog, since they use a global set of variables.

How about

created:
sethinguserdata(getsenderref(), creathing(getsenderref(), ghost));

Then in a thing pulse/thing timer, check the distance between the pot and its originating ghost (snagged through userdata). If its to far away from its original position, teleport thing back to the ghost. You could also add a provision to check if the players have either the original location or pot in view, and just reset the timer if thats the case. This is a similar system to that hard coded in JK to remove enemy corpses. It creates a more seamless effect.
-El Scorcho

"Its dodgeball time!" -Stormy Waters
2005-08-11, 1:31 PM #9
[QUOTE=jedi I]I also don't want 50 different vase templates and cogs because I would be
putting all of the powerups in vases and that would be annoying and unefficient.[/QUOTE]
Don't do that for all of the weapons. Weapon pickups are vital hotspots of a map. Removing them cripples gameplay.
[QUOTE=El Scorcho]sethinguserdata(getsenderref(), creathing(getsenderref(), ghost));
[/QUOTE]
The problem with this is that we are already using the user data to store the health.

I didn't have time today to give the level cog another try, but I promise to have done so until sunday evening.
"Häb Pfrässe, süsch chlepfts!" - The coolest language in the world (besides Cherokee)
2005-08-11, 4:50 PM #10
Originally posted by zagibu:
The problem with this is that we are already using the user data to store the health.


in the class cog for the vase

created:
locator = creatething(getsenderref(), specialghost);
setthinguserdata(locator, getsenderref());

And then give the specialghost template its own class cog,
created:
setthingpulse(getsenderref(), 2.0);

pulse:
check distance and LOS player business
if yes then
teleportthing(getthinguserdate(getsenderref()), getsenderref());

In short, just have the the ghost locator thing do this work instead.
-El Scorcho

"Its dodgeball time!" -Stormy Waters
2005-08-11, 8:45 PM #11
Use heap.

HeapNew(GetThingCount() * 3);
HeapSet(vaseThing * 3, VectorX(originalpos));
HeapSet((vaseThing * 3) + 1, VectorY(originalpos));
HeapSet((vaseThing * 3) + 2, VectorZ(originalpos));

SetThingPos(destroyedVase, VectorSet(HeapGet(destroyedVase * 3), HeapGet((destroyedVase * 3) + 1), HeapGet((destroyedVase * 3) + 2)));

If you want to throw in sector, change it to 4, and use ((vaseThing * 3) + 3)

The heap and vectors are the true godsends of cog.
_ _ _____________ _ _
Wolf Moon
Cast Your Spell On Me
Beware
The Woods At Night
The Wolf Has Come
2005-08-11, 10:45 PM #12
Well, my level is in the final stages and I can't finish item placement until I know
if I am using vases for all the powerups or if I'll just us conventional powerups.
I am truly greatful for all the efforts that you guys have put in for this cog. I'd
like to move on and am completely satisfied with the current cog. If you really
want to finish what you've started then I'll be willing to give that chance so that
you efforts don't get made in vain. I've actually thought about it and I think that
additional force throw Items will be better. I am going to try to complete Item
placement and remove the throwablity from the template using the vases as the
main source of power ups.
If curiosity killed the cat then perhaps Curious George killed the cat.
But Cat's do have nine lives so who knows?
2005-08-12, 12:05 AM #13
Originally posted by LKOH_SniperWolf:
Use heap.

HeapNew(GetThingCount() * 3);
HeapSet(vaseThing * 3, VectorX(originalpos));
HeapSet((vaseThing * 3) + 1, VectorY(originalpos));
HeapSet((vaseThing * 3) + 2, VectorZ(originalpos));

SetThingPos(destroyedVase, VectorSet(HeapGet(destroyedVase * 3), HeapGet((destroyedVase * 3) + 1), HeapGet((destroyedVase * 3) + 2)));

If you want to throw in sector, change it to 4, and use ((vaseThing * 3) + 3)

The heap and vectors are the true godsends of cog.

I don't see what that would change. The heap will still be overwritten by every other vase. Class cogs use a common set of variables, they don't have independent sets for each instance. This obviously counts for the heap, too.

Originally posted by jedi I:
Well, my level is in the final stages and I can't finish item placement until I know
if I am using vases for all the powerups or if I'll just us conventional powerups.
I am truly greatful for all the efforts that you guys have put in for this cog. I'd
like to move on and am completely satisfied with the current cog. If you really
want to finish what you've started then I'll be willing to give that chance so that
you efforts don't get made in vain. I've actually thought about it and I think that
additional force throw Items will be better. I am going to try to complete Item
placement and remove the throwablity from the template using the vases as the
main source of power ups.

Again, I advise you against putting ALL the powerups in vases. The vases are a cool touch, but there must also be places where you get this and that powerup FOR SURE. This is really important for gameplay, trust me.
Good examples for powerups that can be "vase only":
- bacta tanks
- ammunition
- fullshield
- power boost
- mana crystals
- sidearms like the bowcaster or thermal detonators
Examples for powerups that MUST be available in set places:
- health and shields
- main weapons: repeater, raildet, concrifle
- force surges, if you want to put some focus on forces
My advice: build a healing chamber (the only place to get health/shields for sure) somewhere in the pyramid, easily accessible, this will be where everyone runs to constantly. You can use a cog to create healing sectors, if you don't want to place healthpacks. Hide the concrifle somewhere deep in the bowels of the pyramid. The raildetonator can be in the open, just don't place a lot of ammo near it. Strifle and repeater should be easy to get, possibly in several places.
This is important: forget your ideas about "realism". Fun will keep the map alive, not "realism". Get advice on item placement from different people, and make sure to run some test sessions.
"Häb Pfrässe, süsch chlepfts!" - The coolest language in the world (besides Cherokee)
2005-08-12, 5:39 AM #14
Heap could be used as a method to solve this through class cog, so long as you have a predetermined max. I've used offsets in heaps to allow me to apply several different variables to a thing when userdata just wasn't enough. I needed it to allow me to create A* searchable path nodes for cog AI.

Assume 1000 things max.

Setheap(1000 * (number of variables per thing + 1))

Thing 1 is stored in heapslot 0.

Thing 1's original vector pos is stored in 1000.

Thing 1's anything else is stored in 2000.

And so on.

Whenever you want to to grab a thing, you just grab its spot then add 1000 for original vector or 2000 for the other value.

This is the only way I think you could really do all of this in a single cog. You could use standard arrays of variables or whatever, but then you'd hit the max cog variable limit pretty fast...its some number under 100 IIRC.

I'm not sure about sniperwolfs usage there...I'm pretty sure zagibu is correct in that the heap values won't be specific to a single instance of the class cog, just like other class cog variables. Also, according to sige's tutorial you can store vectors in heaps without having to break them into their respective pieces so that much should be unnecessary. I actually haven't had a need to do this yet.

Still...I don't see any problem with my original method, it simple requires an extra template and small class cog. I suppose it depends on your definition of elegant...I've used some pretty ugly hacks to make things work in JK before. The special finder thing should spawn on its own without any intervention required by the level editor.
-El Scorcho

"Its dodgeball time!" -Stormy Waters
2005-08-12, 7:19 AM #15
Ah, now I see what you are getting at. You are using the thing's id as heap index. That could really work.
"Häb Pfrässe, süsch chlepfts!" - The coolest language in the world (besides Cherokee)
2005-08-12, 7:44 AM #16
Well...sort of. Do you mean the thing number by thing id?

I mean, you can't just say heapget(thispot) because thats going to grab the heap position with the same slot number as the thing number. All we're really doing is just creating a multidimensional array...which is easy enough in C++ but not *really* possible in cog. However, this is an affective simulation of one, its only limitation is there is a a reasonable upper limit (since if you had 1001 things it would screw everything up)

If you want a specific thing and its data, you'll have to use a for loop through the first set of the "array" and thing numbers against eachother to find its position in the "array" then store an offset. This all got really complex in my A* cog...but I got it working solid eventually.

For your purposes it should be fairly simple. You've only got two things to compare the original vector pos and the actual thing, and you're not going to have to search to find a specific one in the class cog you just go through the list, because you want to do this to all of the things regardless.

Have a global count variable, in startup HeapNew(2000); potcount = 0; setpulse(3.0); //can we do regular pulse's in class cogs? I can't remember.

In created:
HeapSet(potcount, getsenderref());
HeapSet(potcount + 1000, GetThingPos(GetSenderRef()));
potcount = potcount + 1;

pulse:
for(i = 0; i = i + 1; i < potcount)
If(vectordist(Getthingpos(HeapGet(i)), HeapGet(i + 1000) ) > 0.2)
SetThingPos(HeapGet(i), HeapGet(i + 1000), sector?);

Of course you'll have to find the sector at pos...I'd just use the mots verb but you'd have to use the code thats in datamaster for JK.
-El Scorcho

"Its dodgeball time!" -Stormy Waters
2005-08-12, 8:04 AM #17
The method I mentioned is basically that multidimensional array. I indeed counted on the fact that each pot would overwrite the heap. So unless two pots magically have the same thing number, the code I gave works absolutely fine for storing and retrieving initial position information.

for an x * y array (where x is row, and y is column starting with 0):

HeapNew(maxX * maxY);
HeapSet(((x * maxY) + y), blah);

No need to use random offsets. And since GetThingCount() returns the maximum possible number of things, using that in place of maxX works great in anything dealing with things. I've been using this method to store info for various things, as an alternative to UserData.
_ _ _____________ _ _
Wolf Moon
Cast Your Spell On Me
Beware
The Woods At Night
The Wolf Has Come
2005-08-12, 8:45 AM #18
Ah! I think see what you're doing now. GetThingCount() grabs the jkl max value right? I wasn't thinking of vasething as being senderref() from created for some reason. I thought you were just running that all once in created or startup and didn't see how it would work.

Thats actually damn clever...you're using the thing number itself as the index. I thought for sure you'd be overwriting things but I'm of course wrong now that I take a close look at it. Same principle, different implementation. It made more sense for me to put the things all in the array when I did this because I only wanted to search through one type of thing in the cog.

Actually, you could use this to add attributes to all things in the level, by just having one master cog handle them...if you didn't mind having say sendmessage or sendtrigger do the communicating between cogs. I was always annoyed that I could only store one variable in userdate...this really provides a workaround for that.

Thanks for the clarification.

Although, I'm still not sure you'd have to break the vector down, in this example anyway.
-El Scorcho

"Its dodgeball time!" -Stormy Waters
2005-08-12, 11:17 AM #19
I have a working cog now, but there are strange synch issues. The vases don't get destroyed on a joiner's machine at all, might be a problem with SetThingUserData(), no idea. We might have to change the template, so that it's got an appropriate health value...

[edit]New code below solves the destroy synch issue, but the vases won't be recreated[/edit]

Code:
# Jedi Knight Cog Script
#
# ACTOR_POT.COG
#
# This cog makes a pot explode if damaged enough
# Possibly creates a powerup
# Actually a class COG
#
# 2005 Jedi I
#                   modified by zagibu@gmx.ch
# ========================================================================================

symbols

thing		victim				local
thing		dummy				local

template	dummy_tpl=_powerup		local
template	exp_tpl=+crate_exp		local
template	powerup0=+dhealthpack		local
template	powerup1=+dbactatank		local
template	powerup2=+dshield		local
template	powerup3=+dbattery		local
template	powerup4=+denergycell		local
template	powerup5=+dpowercell		local
template	powerup6=+dsmbp			local

sound		respawn_snd=Activate01.wav	local

vector		original_position		local

sector		original_sector			local

flex		life=40				local
flex		wait_time=30			local
flex		health				local
flex		damage				local
flex		rval				local
flex		geo_mode			local
flex		collide_type			local

int		init=0				local

message		startup
message		created
message		damaged
message		timer

end

# ========================================================================================

code

startup:
	// Initialize control variables
	init = 0;
	Return;

# ........................................................................................

created:
	victim = GetSenderRef();

	if(!init)
	{
		// Create the heap
		HeapNew(GetThingCount() * 3);
		init = 1;
	}

	// Save the sector and position of the victim on the heap
	HeapSet(victim * 4, GetThingSector(victim));
	HeapSet(victim * 4 + 1, GetThingPos(victim));
	HeapSet(victim * 4 + 2, -1);
	HeapSet(victim * 4 + 3, life);

	Return;

# ........................................................................................

damaged:
	victim = GetSenderRef();
	health = HeapGet(victim * 4 + 3);
	damage = GetParam(0);

	// Check type of damage and handle impact damage as a special case
	if(GetParam(1) & 0x1)
	{
		// Check if a player has applied impact damage to the victim
		if(GetThingType(GetThingParent(GetSourceRef())) == 10)
			Return;
	}

	// Are we applying enough damage to "kill" the poor thing
	if(damage >= health)
	{
		// Create the explosion template at the damaged thing's position
		CreateThing(exp_tpl, victim);

		// Remove the victim (render it invisible and disable it's collision switch)
		geo_mode = GetThingCurGeoMode(victim);
		SetThingCurGeoMode(victim, 0);
		collide_type = GetCollideType(victim);
		SetCollideType(victim, 0);

		// Start the respawn timer
		SetThingTimer(victim, wait_time);

		// Create a random powerup at the victim's position
		rval = Rand();
		if (rval < 0.15)
		{
			dummy = CreateThing(powerup0, victim);
		}
		else if (rval < 0.35)
		{
			dummy = CreateThing(powerup1, victim);
		}
		else if (rval < 0.45)
		{
			dummy = CreateThing(powerup2, victim);
		}
		else if (rval < 0.46)
		{
			dummy = CreateThing(powerup3, victim);
		}
		else if(rval < 0.61)
		{
			dummy = CreateThing(powerup4, victim);
		}
		else if(rval < 0.66)
		{
			dummy = CreateThing(powerup5, victim);
		}
		else if(rval < 0.67)
		{
			dummy = CreateThing(powerup6, victim);
		}

		HeapSet(victim * 3 + 2, dummy);
	}
	else
		HeapSet(victim * 4 + 3, health - damage);

	Return;

# ........................................................................................

timer:
	victim = GetSenderRef();
	original_sector = HeapGet(victim * 4);
	original_position = HeapGet(victim * 4 + 1);

	if(VectorDist(GetThingPos(victim), original_position) != 0)
	{
		dummy = CreateThingAtPos(dummy_tpl, original_sector, original_position, '0 0 0');
		SetThingRotVel(dummy, '0 0 0');
		TeleportThing(victim, dummy);
		DestroyThing(dummy);
		dummy = HeapGet(victim * 4 + 2);
		if(dummy != -1)
		{
			DestroyThing(dummy);
			HeapSet(victim * 4 + 2, -1);
		}
	}

	// Respawn the victim (render it visible and enable it's collision switch)
	SetThingCurGeoMode(victim, geo_mode);
	SetCollideType(victim, collide_type);

	// Reset the victim's health
	HeapSet(victim * 4 + 3, life);

	// Play the respawn sound
	PlaySoundThing(respawn_snd, victim, 1, 0, 8, 0x0);

	Return;

end
"Häb Pfrässe, süsch chlepfts!" - The coolest language in the world (besides Cherokee)
2005-08-12, 6:44 PM #20
Yeah. Most likely, the things existence, position and orientation are synced when they join, and then created is run locally. You could just on a join:

In created, check to see if the player is the host. (PlayerNum 0 is host)
If not; SendTrigger to player 0; Player 0 responds (Via a for loop), with thing number, and its current health. You could fit two vases per trigger (using minor sleep in between). If it happens to be an odd number of things, send a -1 in place of thing number.
_ _ _____________ _ _
Wolf Moon
Cast Your Spell On Me
Beware
The Woods At Night
The Wolf Has Come
2005-08-16, 12:49 PM #21
Damn, I almost had a working version with _throwables, but then I somehow produced an infinite loop and gave up.
Here are two cogs that work with non-moving pots. The first one is the class cog:
Code:
# Jedi Knight Cog Script
#
# ACTOR_POT.COG
#
# This cog makes a pot explode if damaged enough
# Possibly creates a powerup
# Actually a class COG
#
# 2005 Jedi I
#                   modified by zagibu@gmx.ch
# ========================================================================================

symbols

thing		victim				local

template	exp_tpl=+crate_exp		local
template	powerup0=+dhealthpack		local
template	powerup1=+dbactatank		local
template	powerup2=+dshield		local
template	powerup3=+dbattery		local
template	powerup4=+denergycell		local
template	powerup5=+dpowercell		local
template	powerup6=+dsmbp			local

vector		position			local

flex		life=40				local
flex		health				local
flex		damage				local
flex		rval				local

message		created
message		damaged

end

# ========================================================================================

code

created:
	// Give the victim it's initial health
	SetThingUserData(GetSenderRef(), life);

	Return;

# ........................................................................................

damaged:
	victim = GetSenderRef();
	
	health = GetThingUserData(victim);
	damage = GetParam(0);

	// Check type of damage and handle impact damage as a special case
	if(GetParam(1) & 0x1)
	{
		// Check if a player has applied impact damage to the victim
		if(GetThingType(GetThingParent(GetSourceRef())) == 10)
			Return;
	}

	// Are we applying enough damage to "kill" the poor thing
	if(damage >= health)
	{
		// Create the explosion template at the damaged thing's position
		CreateThing(exp_tpl, victim);

		// Create a random powerup at the victim's position
		rval = Rand();
		if (rval < 0.15)
		{
			CreateThing(powerup0, victim);
		}
		else if (rval < 0.35)
		{
			CreateThing(powerup1, victim);
		}
		else if (rval < 0.45)
		{
			CreateThing(powerup2, victim);
		}
		else if (rval < 0.46)
		{
			CreateThing(powerup3, victim);
		}
		else if(rval < 0.61)
		{
			CreateThing(powerup4, victim);
		}
		else if(rval < 0.66)
		{
			CreateThing(powerup5, victim);
		}
		else if(rval < 0.67)
		{
			CreateThing(powerup6, victim);
		}

		// Send the destruction notification
		position = GetThingPos(victim);
		SendTrigger(-1, 133701, VectorX(position), VectorY(position), VectorZ(position), -1);

		// Remove the victim
		DestroyThing(victim);
	}
	else
		SetThingUserData(victim, health - damage);

	Return;

end


The second one is a level cog, which controls pot respawning:
Code:
# Jedi Knight Cog Script
#
# ACTOR_POT_CONTROL.COG
#
# This cog respawns a pot with class cog ACTOR_POT.COG
# Actually a level COG
#
# 2005 Jedi I
#                   modified by zagibu@gmx.ch
# ========================================================================================

symbols

template	pot_tpl=pot

sound		respawn_snd=Activate01.wav

thing		dummy				local
thing		ghost0=-1
thing		ghost1=-1
thing		ghost2=-1
thing		ghost3=-1
thing		ghost4=-1
thing		ghost5=-1
thing		ghost6=-1
thing		ghost7=-1
thing		ghost8=-1
thing		ghost9=-1

vector		insert_offset
vector		sent_position			local
vector		current_position		local

flex		dist_temp			local
flex		respawn_time=30

int		i				local

message		startup
message		trigger
message		timer

end

# ========================================================================================

code

startup:
	if(!isServer())
		Return;

	// Create the pots
	for(i = 0; i < 10; i = i + 1)
		dummy = CreateThing(pot_tpl, ghost0);

	Return;

# ........................................................................................

trigger:
	if(GetSourceRef() != 133701)
		Return;

	sent_position = VectorSub(VectorSet(GetParam(0), GetParam(1), GetParam(2)), insert_offset);

	// Check all ghosts
	for(i = 0; i < 10; i = i + 1)
	{
		current_position = GetThingPos(ghost0);
		dist_temp = VectorDist(current_position, sent_position);
		if((dist_temp < 0.001) && (dist_temp > -0.001))
		{
			SetThingTimer(ghost0, respawn_time);
			i = 10;
		}
	}

	Return;

# ........................................................................................

timer:
	dummy = CreateThing(pot_tpl, GetSenderRef());
	PlaySoundThing(respawn_snd, dummy, 1, 0, 10, 0x0);

	Return;

end


Note: you must find out the insert offset of you pots (look in the 3do file) and enter it as insert_offset parameter, or the cog won't respawn anything. This is because a via CreateThing created thing's position differs from the originating thing's position by this insert_offset.

P.S. If you still sthink _throwable vases would be kewl, I can give the cogs another try tomorrow. I was really close, you know.
"Häb Pfrässe, süsch chlepfts!" - The coolest language in the world (besides Cherokee)
2005-08-17, 8:25 PM #22
here's a cog that kind of does what you want
it needs to be modified for your pot needs
if you want to test it just add it to a standard
throw crate and put the name of the template you use
in the CRATE_TPL symbol
Code:
##########################################################
# Jedi Knight Cog Script
#=========================================================
# thro_cratexp01.COG
# -CLASS COG
# -when the crates are damaged enough they explode and
#  after a delay respawn in their original position
# ========================================================
# Written By DSLS_DeathSythe
# This Cog is Not supported by LucasArts Entertainment Co.
##########################################################
symbols
#---------------------------------------------------------
message	startup
message	damaged
message	timer

template	crate_tpl=cratetest01			local
template	exp_tpl=+grenade_exp			local

int		heap_MAX=0					local
flex		respawn_DELAY=5.0				local
flex		hlth_MAX=100.0				local

int		a=0						local
int		b=0						local
int		c=0						local
vector		vec						local

int		dmg_sender=-1					local
flex		damage=0.0					local
int		dummy=-1					local
#---------------------------------------------------------
end
#=========================================================
code
#---------------------------------------------------------
startup:
	sleep(2.0);

	//-Get the number of things with the crates template
	a = GetThingTemplateCount(crate_tpl)+1;

//PrintInt(a);

	//-Set the heap size to a*4
	heap_MAX = a*4;
	HeapNew(0, heap_MAX);

	//-set all the heaps spots to -1
	for(b=0; b<heap_MAX; b=b+1)
		{
		HeapSet(b, -1);
		}

	//-fill the heap with the info of the crates
	b=0;
	for(a=0; a<GetThingCount(); a=a+1)
		{
		if(GetThingTemplate(a) == crate_tpl)
			{
			c=GetThingSector(a);
			vec = GetThingPos(a);
			HeapSet(b, a);  //-ID =+0
			HeapSet(b+1, c);  //-sector =+1
			HeapSet(b+2, vec);  //-vector =+2
			HeapSet(b+3, hlth_MAX);  //-health =+3
			b=b+4;
			}
		}
return;
#---------------------------------------------------------
damaged:
//Print("crate damaged");
	dmg_sender = GetSenderRef();
	damage = GetParam(0);
	//-check the heaps thing IDs for who was damaged
	for(a=0; a<heap_MAX; a=a+4)
		{
		b = HeapGet(a);
//PrintInt(b);
		if(b == dmg_sender)
			{
//PrintInt(b);
			c = HeapGet(a+3);
			c = c - damage;
//PrintFlex(c);
			HeapSet(a+3, c);
			if(c <= 0.0)
				{
//Print("BOOOM!!!");
				CreateThing(exp_tpl, b);
				SetTimerEx(respawn_DELAY, a, 0, 0);
				DestroyThing(b);
//				c = 10000.0;
//				HeapSet(a+3, c);
				}
			a = heap_MAX+1;
			}
		}
return;
#---------------------------------------------------------
timer:
	//-Respawn the crates in their original positions
//Print("respawning");
	a = GetSenderID();
	b = HeapGet(a+1);  //-Get the sector
	vec = HeapGet(a+2);  //-Get the vector
	dummy = CreateThingAtPos(crate_tpl, b, vec, '0 0 0');  //-Create the crate
	HeapSet(a, dummy);  //-Update the things ID in the heap
	HeapSet(a+3, hlth_MAX);  //-Set the crates health to max
return;
#---------------------------------------------------------
end
##########################################################

mostly it just does what everyone has been saying to do with the heap stuff
the crates health is managed in the heap too
and i havent tested it in MP
maybe you can use some of it
Famous last words - "It seemed like a good idea at the time."
2005-08-19, 7:38 AM #23
Thanks for the cog. I think I will use it. Because it lacks the aspect of
creating a powerup when destroyed I will just provide additional items.
This will make my template work a bit easier. Thanks guys. I'll try to
get this rolling and then get a beta up today. If not at least I'll get it
in the next week or two.
If curiosity killed the cat then perhaps Curious George killed the cat.
But Cat's do have nine lives so who knows?

↑ Up to the top!