(Pointer selectors are bitwise flags from the enum type AAPTR. They are parameters in several of the newer code pointers.)
Standard selectors:
AAPTR_DEFAULT: will point to the "normal" target, "self" in most cases; exceptions noted where "self" is not a logical choice
AAPTR_NULL: will not point to a target
Standard selectors, assignable:
AAPTR_TARGET
AAPTR_MASTER
AAPTR_TRACER
Special selectors (not assignable):
AAPTR_PLAYER_GETTARGET: Usable in bitwise combination with standard selector. Will override any standard selector (including DEFAULT and NULL) if the caller/source is a player. Will get player's linetarget.
Spoiler: Additional special selectors that made it in to the r3218M-edition
AAPTR_PLAYER_GETCONVERSATION: Usable whenever the player has a conversation NPC assigned. I only know with certainity that it is useful with CustomInventory objects given during conversation, but I also know that it is extremely useful in that regard. It allows for powerful generic interactions between player and NPC through Strife dialogue.
AAPTR_PLAYER#: Direct access to player 1-8. Works no matter who the caller is. Non-existent players return null pointers. Very useful for situations that would normally require a tid lookup. Use of this feature increases mod-compatibility, as new mods need not depend on mod-specific tid assignments for relatively simple player interactions.
Spoiler: Technical note
One useful thing which is true of this code, is that { AAPTR_PLAYER1<<"offset" } equals the pointer to another player. AAPTR_PLAYER1<<0 == AAPTR_PLAYER1, AAPTR_PLAYER1<<1 == AAPTR_PLAYER2, AAPTR_PLAYER1<<7 == AAPTR_PLAYER8. We might want to make this behaviour "documented" and guaranteed to persist. For up to 8 players anyway. (This feature is particularly useful when/if these actor selectors are made available to ACS. SetActivator can easily be extended to make good use of these pointers.)
AAPTR_FRIENDPLAYER: If a monster is friend to a particular player, this will point to that player.
Relevant code pointers as programmed in this patch:
A_GiveInventory(string type, int count, int pointer_selector = AAPTR_DEFAULT)
Previously existing function definition. Benefits from addition of AAPTR_PLAYER_GETTARGET.
A_GiveToTarget(...) { DEPRECATE? }
Fully backwards compatible (including its inability to acquire a player's target). A_GiveInventory duplicates and extends A_GiveToTarget.
FIX: Default pointer-selector (AAPTR_DEFAULT) added to prevent undefined behaviour.
A_TakeInventory(string type, int count, int flags, int pointer_selector = AAPTR_DEFAULT
Previously existing function definition. Benefits from addition of AAPTR_PLAYER_GETTARGET.
A_TakeFromTarget(...) { DEPRECATE? }
Fully backwards compatible (including its inability to acquire a player's target). A_TakeInventory duplicates and extends A_TakeFromTarget.
FIX: Default pointer-selector (AAPTR_DEFAULT) added to prevent undefined behaviour.
A_JumpIfInventory(string type, int amount, str|int state, int pointer_selector = AAPTR_DEFAULT)
Extended to use a selected pointer for the inventory check. (Similar to already added extension for A_GiveInventory and A_TakeInventory.)
A_JumpIfInTargetInventory(...) { DEPRECATE? }
Fully backwards compatible (including its inability to acquire a player's target). A_JumpIfInventory duplicates and extends A_JumpIfInTargetInventory.
PREEMPTIVE: Default pointer-selector (AAPTR_DEFAULT) added to prevent undefined behaviour.
Spoiler: A_TransferPointer
A_TransferPointer(int aaptr_ptr_owner, int aaptr_ptr_recepient, int aaptr_ptr_selector, int aaptr_ptr_assignment, int pointer_operation_flags)
Previously existing function definition. Benefits from addition of AAPTR_PLAYER_GETTARGET for all parameters but aaptr_ptr_assignment. (Assignment can only be made to TARGET|MASTER|TRACER)
Quick parameter summary (mostly unchanged)
aaptr_ptr_owner: Select the actor, available to the caller, that has the pointer to be copied. AAPTR_DEFAULT will select the caller.
aaptr_ptr_recepient: Select the actor, available to the caller, that will store the copied value. AAPTR_DEFAULT will select the caller.
aaptr_ptr_selector: Select the pointer to be copied from the selected "owner". AAPTR_DEFAULT will select the "owner".
aaptr_ptr_assignment: Select the pointer to be assigned (target|master|tracer only) in the "recepient". Same value as "aaptr_ptr_selector" by default.
pointer_operation_flags:
PTROP_UNSAFETARGET = 1; (Don't null assignments that result in an infinite chain of missiles referencing eachother)
PTROP_UNSAFEMASTER = 2; (Don't null assignments that result in an infinite chain of actors referencing eachother)
PTROP_NOSAFEGUARDS = PTROP_UNSAFETARGET|PTROP_UNSAFEMASTER;
A_JumpIfTargetInLOS(...)
Added flags:
JLOSF_TARGETLOS: Check target's line of sight
JLOSF_FLIPFOV: Check FOV for the actor that does not make a sight check
JLOSF_ALLYNOJUMP: Jump only if the actors are not allied to eachother. Unfriendly monsters have no allies.
JLOSF_COMBATANTONLY: Jump only if the target is a monster or a player. (Particularly useful when working with a player's target, as it could be any actor.)
JLOSF_TARGETLOS|JLOSF_FLIPFOV: Duplicates behaviour of A_JumpIfInTargetLOS (target line is checked, caller fov is checked)
The duplication is not exact: A_JumpIfInTargetLOS always uses the stored pointers, even for players. A_JumpIfTargetInLOS uses linetargets for players. A_JumpIfInTargetLOS should normally not work with a player caller, as they would normally have no stored pointers.
A_JumpIfInTargetLOS(...) { DEPRECATE ? }
No changes introduced. This function has very little remaining value. Nothing it could do cannot now be done at least as well without it.
A_CheckFlag(string flagname, int|string statejump, int pointer_selector = AAPTR_DEFAULT)
New code pointer. Jump if the indicated actor (self by default) has the named flag. Like all such functions, it performs no jump if the selected actor does not exist.
Developers / moderators: Please pardon the multithreading. The existing forum threads can be kept for reference, or in case this merged patch cannot be added. If this patch is added, you can delete|no|already in|add or anything to the existing threads. The patch in this thread covers everything.
Spoiler: Demo description
Punch dagger
Fire: Regular attack
Altfire: Slow double damage attack. If you manage to stay on a bleeding monster that doesn't catch you in its field of view, you deal 5x damage.
(Damage increase is achieved through multiple 0-tic calls to A_JabDagger)
Missile launcher
Fire: Regular attack
Altfire: Try to find a target within field of view or perfect aim and make adjust course for it after a few tics. Semi-seeking missile. Cool, and not always better than a straight shot, but often much easier to get your target. Reduces the impact of low accuracy early in game.
Many projectiles have increased speed, making them easier to aim and slightly more responsive. Grenades also gain increased range from this speed increase, since gravity tends to bring them down.
Crossbows: Altfire readies the bow for a precise shot; repeat altfire to perform the precise shot. Precision gain only applies at low/very low speeds. Crossbow state is not maintained when moving between maps or changing weapons; if it was ready, it must be readied again.
Assault gun: Altfire fires at reduced rate with full accuracy. Has proven excellent for taking out targets from cover because you can track your puffs shot by shot until you find your target.
Grenade launcher: No longer fires double shots automatically. Alternates barrels as long as you hold fire. Main fire starts with right barrel, altfire starts with left barrel.
Flamethrower: No changes (well, I might have meddled with the flame translucency, but I don't think I achieved much. They still seem damned solid, so those changes might not be worth anything).
Mauler: Reduced ammo consumption for the shitty shot. Added primary weapon altfire that vaguely resembles the assault gun in its performance, although it is not affected by accuracy. Sister weapon recoloured to make the visual distinction more obvious. Added sister weapon altfire that executes very low damage hitscans in rapid succession with perfect aim.
Game balance: This mod makes the game very easy. It needs a counterpart in the monster department. Or play on Bloodbath! Whew, this is taxing!
EDIT: Further possible additions, that could be merged directly into this patch, exist. See my second post, directly after Major Cooke's.
Edit: After noting in another project that new files aren't automatically part of the diff, I found it to be true of actorptrselector.h as well. Reuploaded in zip-archive with the diff and the new code file. Is there a SlikSvn setting I am missing? (12.05 2011)
EDIT: Attachments removed; they have served their purpose.
Last edited by FDARI on Thu Oct 27, 2011 9:58 am, edited 19 times in total.
Topic of this message: I have even more extensions at home, of improved design and increased capability.
I have made some further extensions to this while working on a project. To make it work, I have moved some of the code. I prefer the new code organisation, because it enables use of the AAPTR-selectors outside of thingdef_codeptr.cpp.
In addition to the organisation change, the following additions exist (any of which can be included in a patch):
Extended ACS function with AAPTR-selector: SetActivator(int tid[, int ptr_selector])
Default behaviour (1 parameter): Unchanged.
Allows the use of any of the defined AAPTR-selectors. The pointer is picked from the actor identified by the tid.
The function behaves the same if the pointer resolves to NULL (no actor) as if the TID does not exist.
New AAPTR-selector: AAPTR_PLAYER_GETCONVERSATION
When a strife dialogue gives you a custom inventory item, you can use AAPTR_PLAYER_GETCONVERSATION to select specifically the actor you're talking to. I have not checked what it will do under other circumstances.
In combination with the ACS extension, this will also allow the use of ACS_ExecuteWithResult (84) being called directly from a strife conversation, provided that the player is treated as the initial activator. I believe this is the case. (I chose "executewithresult" because that special will begin script execution immediately. However, I have not tested this yet.)
Is there any way you can extend some functionality to A_SeekerMissile/A_LookEx for projectiles in the form of FOV range? +SCREENSEEKER is simply not enough, and I would like to be able to limit the actual tracer acquiring so that it willbe more useful when attempting to have a missile fire multiple projectiles all at different enemies at once, without targeting the same one multiple times.
Currently, we can only keep clearing and retargeting the same monster, even if it has something like an inventory actor to make the projectile forget about him.
I think there are ways to work around this using existing features; I'm trying at home and coming rather close, but it involves a mix of acs and decorate and a delicate understanding of what we are working with. My solution is a) not yet functional, b) not easy to implement, c) not necessarily efficient. However, I want to see how feasible it is to achieve what you ask for without extending zdoom.exe. I might complete the attempt, and indeed parts of what you ask are probably covered in my chain-lightning (submitted elsewhere) and the missile-launcher's use of A_LookEx.
Possible future code submission
Spoiler: Simplest version
New flag: LOF_SEEKERMISSILE
Friendliness is checked with the shooter (TARGET) instead of with the projectile (caller).
Flag for disabling sound-check exists; will not be implicit in LOF_SEEKERMISSILE.
Existing target-information should be checked in TRACER or not at all. There is extra logic regarding the target pointer (soundtarget, oldtarget; zdoom.exe internals), so LOF_SEEKERMISSILE might ignore all of this.
New target-information needs to be saved to TRACER.
If the caller has no shooter (TARGET) the function should fail as if no valid target (for TRACER) was found.
Less simple version: Having considered the implications, I eventually decided (for now) against this. When more advanced customisation than a clearly defined LOF_SEEKERMISSILE is required, it can probably be handled equally well or better with the use of A_TransferPointer or A_RearrangePointers, as well as A_CopyFriendliness.
The A_LookEx-code is long, branched and deep; I'll see what I can do. I should probably take a first look at extending A_SeekerMissile for similar purposes as well. However, A_LookEx is already a versatile target acquisition function, and versatile target acquisition for seeker missiles is what you want. A_SeekerMissile might need most or all of A_LookEx appended (duplicate code and added parameters) to perform the same task.
I have examined the possibilities for extending A_LookEx. I don't think I will do anything about it. Not much I can do beyond creating a flag that does what decorate can already do in a few more steps.
The decorate way:
Spoiler: Actor code flow
Fire a custom missile.
The missile may or may not have +SEEKERMISSILE.
Assuming that +SEEKERMISSILE is set:
TARGET = Firing player
TRACER = Tracer target
1 - Spawn:
IF you want to keep any initial target; A_JumpIfTargetInLOS with the missile-variant and no sight check can skip to a regular "Seeker"-state.
2 - PrepareForNewTarget:
A_RearrangePointers(AAPTR_DEFAULT, AAPTR_TARGET) [ no change in target, set master to target, no change in tracer ]
A_CopyFriendliness [ match friendliness with pointer (master by default) ]
A_ClearTarget [ remove all kinds of targeting information ]
A_LookEx [look with all kinds of conditions; jump to "TargetAcquired" ]
3 - No target found
Either vanish (0 tic state + stop, no post-processing required) or
A_ChangeFlag("FRIENDLY", false) [ missiles don't need friends ]
A_RearrangePointers(AAPTR_MASTER, AAPTR_NULL, AAPTR_NULL) [ move master back to target, null master, null tracer ]
go to some state suitable when a target is not acquired
4 - TargetAcquired:
A_ChangeFlag("FRIENDLY", false)
A_RearrangePointers(AAPTR_MASTER, AAPTR_NULL, AAPTR_TARGET) [ set acquired target to tracer ]
go to some state suitable when a target is acquired
I think these tools are the best we will have until Doomscript.
Hm. I just realised that my recently reuploaded flexible-diff.zip contains additional pointer constants for zdoom.exe. I had not intended to submit them yet. The new pointer constants are not reflected in the decorate-constant-definition.
Since they're up there, I'll list them and explain them anyway.
AAPTR_PLAYER_GETCONVERSATION: Works with a player activator. Only expected to work while a conversation is active. Tested in use from a custominventory-descendant given by a dialogue script. Might also work within script-specials (especially execute-with-result, if it runs immediately during strife conversation).
AAPTR_FRIENDPLAYER: Works with a monster dedicated to a specific player. (Is null for anything else, which might also be what you are interested in determining.)
These all give a direct reference to an existing player, if the player exists. Can be used to iterate players for changes and state-checks without the use of special tids.
None of the uploaded code contains the modified SetActivator for ACS with the optional second argument (which is one of these pointers).
The latest features lack decorate definitions in pk3 because they were not planned for submission. Nevertheless, I'll add a full-featured diff from the latest zdoom.exe the next time I work on these things.
I'm tempted to try and make it somehow, though I figured I'm quite a lot less intelligent at coding than you are... but I'm still going to try. If you like the idea, perhaps we could come up with something together.
Check out zdoom_pack_r3218M.zip in original post.
Features all the things that were partially implemented in the previous posting.
Please test it viciously.
EDIT: Reuploaded now with improvements to actorptrselect.h. I removed some code duplication and got rid of the bulky #define macros.
Actor pointer selections now have a clearly defined order of priority:
There are three categories of pointer selectors: PLAYER, GENERAL and STATIC.
Whenever a PLAYER pointer is specified and applicable (the source actor is a player), the PLAYER pointer is used.
Otherwise, if a GENERAL pointer is specified and applicable (there is a source actor), the GENERAL pointer is used.
Otherwise, if a static pointer is specified (NULL, or one of the players), the PLAYER pointer is used.
Otherwise, the source actor is returned.
Any of the steps may return NULL. Containing a NULL value does not make a selector unapplicable.
Only one selector can be specified from each category. (use bitwise OR to combine selectors from different categories)
Selectors per category:
Player
AAPTR_PLAYER_GETTARGET, AAPTR_AAPTR_PLAYER_GETCONVERSATION
General
AAPTR_TARGET, AAPTR_MASTER, AAPTR_TRACER, AAPTR_FRIENDPLAYER
Static
AAPTR_PLAYER# (numbers 1 through 8), AAPTR_NULL