Decorating stuff.

Archive of the old editing forum
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. This forum is archived - please use this set of forums to ask new questions.
User avatar
Sphagne
Posts: 513
Joined: Wed Jul 16, 2003 3:36 am

Decorating stuff.

Post by Sphagne »

OK, people, I am going to suggest some ideas that are a big change in concept of DECORATE, but a real good one, and maybe not so big in required work, so please look kindly at these suggestions, pretty please. :smile:

**********************************************

Remember the tag values that I had suggested in my first post in this thread?

How about extending them just a little bit to have some real programming ability here:

First of all, it would be good if we had more than one of those tags for each actor, for instance about 16 of them or any amount that you preffer, in an array like this:

int Variable[16];

Variable[0] is read only, and always contains the actor's index in the game's actor array.
Variable[1] contains the actor's user, and it is read only.
Variable[2] contains the actor's killer, and it is read only.
Variable[3] contains the actor's current target, and we can change it on the fly.

Variable[4]...Variable[15] usable for other purposes.

**********************************************

Action functions:

A_SetVariable( int index, int val1, int val2 )

Variable[index] = Random(val1,val2)

A_ChangeVariable( int index, int val1, int val2 )

Variable[index] = Variable[index]+Random(val1,val2)

A_CopyVariable( int index1, int index2 )

Variable[index2] = Variable[index1]

A_CompareVariables( int index1, int index2, int index3 )

if Variable[index1] < Variable[index2] then set Variable[index3] to -1
if Variable[index1] = Variable[index2] then set Variable[index3] to 0
if Variable[index1] > Variable[index2] then set Variable[index3] to 1

A_Jump_if_Variable_in( int index, int val1, int val2 )

if Variable[index] is inside the range (val1---val2) then jump.

ACS functions:

Actor_SetVariable( int tid, int index, int value )
Changes the the specific actor Variable, tid of 0 means the activator's variable.

int Actor_GetVariable( int tid, int index)
Gets one of the actor's variable's content.

**********************************************

If we had a function like Random( int val1, int val2), that we could use in DECORATE definitions, we could simplify the last section like this:

Action functions:

A_SetVariable( int index, value )

Variable[index] = value

A_ChangeVariable( int index, value )

Variable[index] = Variable[index]+value

...

**********************************************

OK now that we have some variables to play with, how about these additions, and removing any action functions that could be replaced by them:

A_Script( int activator_index, ... )

Calls a script, and sets the activator to the stored actor inside Variable[activator_index].
this means 0 is the current actor, and 1 is the user... and values bigger then 3 can be stored actors for later refrence, like:

A_CopyVariable(3,7), would store the current hate target inside Variable[7], and if there is no actor by the index of Variable[7], it would do nothing.

A_Special( int activator_index, ... )

Calls the special, and sets the activator to the stored actor inside Variable[activator_index]

**********************************************

A_GetHealth( int actor_index, int Index )

Variable[index] = Actor( Variable[actor_index] ) --> GetHealth;

A_SetHealth( int actor_index, int index )

Actor( Variable[actor_index] ) --> SetHealth( Variable[index] )

A_GetDistance( int actor_index, int index )

Variable[index] = GetDistance( Self, Actor( Variable[actor_index] ) );

A_GetSectorLight( int actor_index, int index )

Variable[index] = GetSectorLight( Actor( Variable[actor_index] ) );

A_GetSpeed( int actor_index, int index )

Variable[index] = GetSpeed( Actor( Variable[actor_index] ) );

A_SetSpeed( int actor_index, int index )

Actor( Variable[actor_index] ) --> SetSpeed( Variable[index] )

**********************************************

A_GetActorVariable( int actor_index, int index, int var_index )

Variable[index] = Actor( Variable[actor_index] ) --> Variable[var_index]

A_SetActorVariable( int actor_index, int index, int var_index )

Actor( Variable[actor_index] ) --> Variable[var_index] = Variable[index]

**********************************************

A_GetFlag( int actor_index, int index, int FlagTag )

Variable[index] = 1 if the specified flag of the specified actor is set, 0 otherwise.

A_SetFlag( int actor_index, int index, int FlagTag )

if Variable[index] is zero, it clears the specified flag of the specified actor, otherwise it would set it.

A_Check_in_WaterZone( int actor_index, int index )

Variable[index] = 1 if specified actor is in water zone, 0 otherwise.

A_Check_in_Sight( int actor_index, int index )

Variable[index] = 1 if the specified actor is in sight, 0 otherwise.

A_Check_Can_See( int actor_index, int index )

Variable[index] = 1 if the specified actor can see the current actor, 0 otherwise.

**********************************************

A_Jump( int steps )

Jump ahead by "steps" frames, "Random" function would take case of the rest.

A_JumpVar( int index )

Jump ahead by Variable[index] frames.

**********************************************

A_DropMarker( int actor_index, int index, bool NoGravity )

Drops a shootable, but invisible and nonblocking marker item at the specified actor, and keeps it's refrence inside Variable[index].

A_RemoveActor( int actor_index, int index )

Removes the specified actor from the game.

A_Check_Teleport( int target_index, int index, bool fog, bool telefrag )

Tries to teleport to the position of the specified target, and if successful, sets Variable[index] to 1, otherwise to 0, and would optionally have a teleport fog or force a telefrag if needed.

**********************************************

Some additional flags:

NORETALIATE: would ignore damage and would not change target.
NOFARATTACKS: would not jump to "Missile" state.
NONEARATTACKS[/b: would not jump to "Melee" state.
FLEETARGET: marks the actor as a flee target.
USETARGET: would not far attack the target and instead of a "Melee" attack, would "Use" it, i.e. forces it to jump to it's "Use" state.

Target has to have HOSTILEUSE it we want it to accept usage from enemy actors, and and if it has FACEUSER flag, then it would face the user actor before trying to call the "Use" state, even if it has no "Use" state.

ACS functions:

Thing_Use( int tid, int target_tid, bool Persistent );

Would set the actor's target to another actor and would set the USETARGET flag od the actor and would optionally set the NORETALIATE flag as well.

**********************************************

A_FindActorByFlags( int index, int max_distance, [FlagSet], [FlagClear] )

Finds the nearest actor that has all the flags in the [FlagSet] and none of the slags in [FlagClear] and places its refrence inside Variable[index], FlagSet can be like: SHOOTABLE+MONSTER+DORMANT... or SHOOTABLE+FLEETARGET...

The actors should be within the max_distance range, and a -1 in the resulting variable, means no matching actor was found.

A_FindPlayer( int index, int max_distance, int player_index )

If player_index is zero then finds the nearest player and places its refrence inside Variable[index], or it would find the specified player, and -1 means not found.

**********************************************

A_Push( int actor_index, int ParaForce, int DiagForce, int ZForce )

Pushes the specified actor to some direction:
ParaForce<0 means it is pulled toward the current actor.
ParaForce>0 means it is pushed away.
DiagForce<0 means it is pushed to left in the eyes of the current actor
DiagForce<0 means it is pushed to right in the eyes of the current actor
ZForce<0 means it is pushed up
ZForce<0 means it is pushed down

We can program MaxRange (of my last suggestion) ourselves.

If we can use the Random function here, then the better.

If the specified actor is the current actor then ParForce is in the currently facing direnction.

**********************************************

OK, here is a way to emulate some particle systems by making our own actors, without excessive A_Script calls and causing probable performance hit, useful to simulate snows and bubbles and smokes:(bigger sprites and translucent), or any other thing you can think of that requires some random or patterned movement around, controlled from inside the actor definitions.

**********************************************

It we do not have "Random" function at hand then we need some actions functions like these:

A_ForceX( int actor_index, int f1, int f2 )
A_ForceY( int actor_index, int f1, int f2 )
A_ForceZ( int actor_index, int f1, int f2 )

These would force the specified actor movement speed in specific directions by a random value between f1 and f2 and note that these values can be negative as well, for instance A_ForceX(-10,10) would act like:

XVelocity=XVelocity+Random(-10,10);

Otherwise we can have a single action function:

A_Force( int actor_index, int ForceX, int ForceY, int ForceZ )

**********************************************

A_ForceVarX( int actor_index, int index )
A_ForceVarY( int actor_index, int index )
A_ForceVarZ( int actor_index, int index )

**********************************************

A_ForceRotateVarZ( int actor_index, int index, int f1, int f2 )

Which can act like the combination of these:

A_ForceX( Random(f1,f2)*Cos( Variable[index] ) )
A_ForceY( Random(f1,f2)*Sin( Variable[index] ) )

It we have "Random" function at hand then:

A_ForceRotateVarZ( int actor_index, int index, int force ).

Combined with actors that were NoGravity LowGravity and Gravity dependant we can make lots of different effects by these.

A_ForceRotateVarX and A_ForceRotateVarY could also be good additions.

**********************************************

And if the actors have a will of their own (i.e. Monsters) then we can simulate some special moments for them, like when they shadder in pain, or they get trapped in a hurricane or tornado(can be triggered by Tag values), or they get a bit dizzy after a hard blow and do some random movement before gaining their ballance:(Declayed actions by the help of Tag loops...).

Note: All these can be programmed into the actor definitions and would not need any ACS code to accompany them, and would be more useful for casual designers, also they would hit performance less than calling ACS functions, because they are compiled code.

P.S. We can make monsters that cast a hurricane spell on their targets and so on...

**********************************************

O.K. I'm waiting for the punishments...
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49230
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Post by Graf Zahl »

Do you really expect someone who has anything to say about it to read it?

It appears your ideas come faster that they can be dismissed, not to mention implemented. And you can be sure, most likely it won't be done. I don't have much interest in it (too much of it is only of marginal or theoretic interest) and I doubt everybody else who could do something about it thinks the same. Doom is an ACTION game, not an RPG. If you are so desperate to have this for your own project why don't you look for a partner who can help you code this stuff?
User avatar
Risen
Posts: 5263
Joined: Thu Jan 08, 2004 1:02 pm
Location: N44°30' W073°05'

Post by Risen »

I just looked at the bold words.

It looks like you've asked for a lot of the same stuff multiple times before. You could at least restrict your requests to things that have not been in discussion already.

And a number of the functions could be done with existing ACS.
User avatar
Sphagne
Posts: 513
Joined: Wed Jul 16, 2003 3:36 am

Post by Sphagne »

I know some of them can be done with ACS, but it some of these that would keep the refrence of the actors inside the internal variables, would be much easier to implement if we had these functions at hand.

And for asking them multiple times, In this case, they are a lot diffenent, if someone takes the trouble and read them, though.

It has the foundational difference of being able to store stuff inside internal variables, stuff like actor refrences and counters... and I was suggesting that if possible, discard my previous suggestions and use these newer ones.

Hey, graf, how about implementing the first sections and ignoring the rest, (until the A_Special)

I'm sure that you will like this when an actual working version is at hand.

Look, we have variable to keep stuff, and can work on these variables, so if we want to check the actor's health for a jump, we can do this:

Sorry I did not mention A_GetHealth would better be Health per cent.

A_GetHealth( 0, 5 ) // place the curent actor's health percent in the Variable[5]
A_Jump_if_Variable_in( 5, 10, 25, 12 )

This means it should jump 12 steps if the current actor's health is between 10 and 25 percent.

A_GetFlag( 1, 7, MONSTER ) // Variable[7]=1 if the user is a monster
A_Jump_if_Variable_in( 7, 1, 1, 2 ) // Jump 2 steps if the user is a monster
A_Push( 1, 25, 0, 12 ) // throws the player characters away
Goto Spawn. // and ignores them.
A_SetVariable( 11, 80, 100 ) // Variable[11]=Random(80,100)
A_PlaySound( HealingSound ); // OK, plays some sound.
A_SetHealth( 1, 11 ) // Sets the user's health to 80--100 percent.
..... // Here be some animation in the monster healer sprites.
Goto Spawn. // OK, thats all.

So no A_Jump_if..... needed, only "A_Jump_if_Variable_in" and maybe "A_JumpVar", and we can do the rest with variable management.

You can keep the current hate target in some variables by:

A_CopyVariable( 3, 6 ) // Variable[6]=Hate Target

And then change it to the nearest flying monster, like this:

A_FindActorByFlags( 7, 0, [MONSTER,NOGRAVITY], [] )
A_CopyVariable( 7, 3 )

And after a while you can return to the previous hate, for the monster that go berserk for a while.

And the last section would let us make snows, and bubles, and the like without calling ACS for each single snowflake, And I dont think that implementing this A_Force is such a big deal but would help us a lot.

Please, at leat, think about this, you said you may implement my tag suggestion, if you had the time, but these variables are not different from that those tags, just 16 instead of 1 and adding an index for the refrence.

The rest, if those variables are available, would look more promising and you may even decide to implement some of them.

And these would normalize the scripts that we can write for our monster behaviour, i.e. we gather some information in variables and work on them and maybe have some output from them.

The Variable[0] could be initialized before calling the Spawn state, and Variable[1], before "Use" state, and Variable[3] before death states, and Variable[4], whenever the hate target is changed. I mean we can keep the hate target here so that if we change that by some action function, we actually change the hate target.

Hey, these are not such a bad ideas, just please dont look at the bulk of them, some of them can be easily abandoned, ( for now :wink: ).

By the way, all of these can be used in action title mods and need not be used in RPGs, this just adds manageable variables and actor refrence keeping to the current DECORATE functionality, which are of quite general usage, some of the rest are implemented already, or you said would be implemented in v64, and the particle systems, are also of general usage, anybody may like snows or bubbles, that already know how to behave, and require no ACS to help each particle.
User avatar
Sphagne
Posts: 513
Joined: Wed Jul 16, 2003 3:36 am

Post by Sphagne »

How about this:

A_SpawnActor( int actor_index, int index, ActorType )

Spawns a type of actor at the position of the specified actor, and keeps it's refrence inside Variable[index].

Thus we can spawn any type of actors over a specified actor, or marker, and keep a refrence of it somewhere to directly work on it later, for instance:

A_SpawnActor( 1, 5, BurningFlame )

// Spawns a burning flame over the User actor, 1 means the user, 5 is the place holder

A_SetActorVariable( 5, 1, 3 )

// and sets the user as the target of the burning flame, 5 is the refrence to burning flame, 1 is the user of the current actor, 3 is the target of the burning flame, and then we can start a loop for some delay:

A_SetVariable( 7, 25, 35 ) // Variable[7]=Random(25,35)

// Loop begining
A_ChangeVariable( 7, -1, -1 ) // Variable[7]=Variable[7]-1
A_Jump_if_Variable_in( 7, 1, 35, Loop_Begining ) // Loops back if Variable[7]>0

A_RemoveActor( 7 ) // Remove the burning flame

This was an example that we can spawn actors and keep a refrence of the spawned actors in an internal variable of the spawner for later refrence, for instance:

Let's say that we have a marker placed somewhere in the level and have it's regrence in Variable[6]:

A_SpawnActor( 6, 7, Dog ) // Spawn a Dog at the marked place and keep it's refrence in Variable[7].
A_SetActorVariable( 7, 3, 3 ) // and make it hate our current target

// Loop 1 beginig
A_GetHealth( 7, 8 ) // Place the dog's health percent in Variable[8]
A_Jump_if_Variable_in( 8, 30, 100, At_The_Loop_1_Begining ) // If more than 30 per cent then loop back

A_Jump_if_Variable_in( 8, -32767, 0, Spawn_State ) // If it is dead then restart...
A_GetActorVariable( 7, 9, 3 ) // Save the dog's current target inside Variable[9]

// Loop 2 beginig
A_SetActorVariable( 7, 1, 3 ) // and make it return to us
A_GetHealth( 7, 8 ) // Place the dog's health percent in Variable[8]
A_Jump_if_Variable_in( 8, -32767, 0, Spawn_State ) // If it is dead then restart...
A_GetDistance( 7, 8 ) // Place the dog's distance from us in Variable[8]
A_Jump_if_Variable_in( 8, 128, 32767, At_The_Loop_2_Begining ) // If further than 128 then loop back

A_PlaySound( .... )
A_SetVariable( 8, 80, 100 ) // Variable[8]=Random(80,100)
A_SetHealth( 7, 8 ) // Give the dog 80--100 percent of it's original health
A_SetActorVariable( 7, 3, 9 ) // and let it pursue it's last target
Goto At_The_Loop_1_Begining

Thus we can spawn an actor and control it's health and behaviour from the actor spawner...

So we gather information into variables and work on them, and then, we may have some output, and if in the future we want to add some more functionality or checks, we can easily add them, by adding some new ways to gather some information into the internal variables and some new ways to output the resulting information, and the rest is compatible with previous fuctionality.

So extending this system is not that hard, and also we can eventually add new ways to work on these variables like summing or multiplying them and other functions, and so on...
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49230
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Post by Graf Zahl »

No.
User avatar
randi
Site Admin
Posts: 7749
Joined: Wed Jul 09, 2003 10:30 pm
Contact:

Post by randi »

A real programming language to create action functions looks like it's much more suited for what you want. These suggestions are even more convoluted than the variable extensions eDuke added to the Duke 3D CON files.
User avatar
Risen
Posts: 5263
Joined: Thu Jan 08, 2004 1:02 pm
Location: N44°30' W073°05'

Post by Risen »

I think for once in a long time, a "Wait for Doomscript" is actually in order here.
User avatar
Sphagne
Posts: 513
Joined: Wed Jul 16, 2003 3:36 am

Post by Sphagne »

OK, people I lose, Sorry. :(

How about that A_Force jobby.
GameArena
Posts: 182
Joined: Wed Jul 16, 2003 4:35 pm
Location: Outside of a bubble... Looking at all the humans inside.

Post by GameArena »

Have you ever looked into the C/C++ programming language, I'm pretty sure that if you were to do so, you could create some nice features. Or even if you couldn't, you'd realize the time and effort it takes to implement them...
User avatar
Mr. Tee
Posts: 1111
Joined: Sun Feb 08, 2004 7:49 pm
Contact:

Post by Mr. Tee »

Sphagne: Yeah, I mean, if you really wanted to implement all these functions in ZDoom, why not take the source code and make your own mod with an IWAD and everything?

I know it's a lot of work for one person, however those suggestions you came up with seem to also take a lot of work, so if you redirected your effort into your own port, you can do as you like!

BTW, Graf is right, DOOM is an action game, not an RPG. It is possible to have limited RPG functionality (i.e. like "Magic Boots" will have) with respect to learning, getting strong with experience, interacting with NPC's, and this makes for an interesting DOOM action experience, however it is still action. True RPG elements (i.e. turn based systems and so on) can never be realized in ZDOOM, as only a minority of people would actually want to edit and play with them.

But that doesn't mean you can't try and make your own port of ZDoom! :wink:
User avatar
Chilvence
Posts: 1647
Joined: Mon Aug 11, 2003 6:36 pm
Contact:

Post by Chilvence »

Yeah, at least give coding a go. It's actually quite easy to make some simple new routines, plus it gives you a warm fuzzy feeling. And if that takes you on toward where you wanna be, it cant be bad.
User avatar
Sphagne
Posts: 513
Joined: Wed Jul 16, 2003 3:36 am

Post by Sphagne »

I have already said that all these suggestion are for general use and do not need to be used for RPG elements, like actor internal variables and actor refrences.., OK, maybe I have to try to do some changes or additions myself, if I can find the time to learn about C basics, That Actor Sight Calculation really needs me to look into it. :wink:
User avatar
HotWax
Posts: 10002
Joined: Fri Jul 18, 2003 6:18 pm
Location: Idaho Falls, ID

Post by HotWax »

Mr. Tee: RPG elements will certainly be possible when DoomScript is done....
User avatar
Chilvence
Posts: 1647
Joined: Mon Aug 11, 2003 6:36 pm
Contact:

Post by Chilvence »

Thats the spirit! If nothing else, try to find a cheap course or find some good online tutorials for it. Or go to a book shop and check out any C/C++ books until you find one that is good for you. Nothing can be done that you dont have the potential to learn to do yourself.
Locked

Return to “Editing (Archive)”