Jump to content

Use PlaceAtMe on an actor other than Player?


TheManWithoutAPlan

Recommended Posts

Hi all,

 

I'm new at modding in general (though I have a background with computers). I have been trying to make a modded spell that turns whatever it hits into a sheep.

 

After reading through some documentation on the wiki, I figured the best way to do this was as follows - make the spell call 'target.PlaceAtMe <Sheep Code>', since the documentation on PlaceAtMe says that it can be used on any actor. After doing this, I could disable the target (to get the 'turned into a sheep' effect).

 

I've been experiencing some troubles with this, though. The code compiles, but it seems to stop executing at this line (any code that comes before that line of the script is still executed). I'm guessing that it is blowing up because I'm doing something wrong and that's why the rest of the script is not getting executed.

 

Although the documentation seemed to suggest that you could use PlaceAtMe with any actor, I have not seen anyone use it outside of using 'Player.PlaceAtMe'.

 

If someone could help me out with this, I would really appreciate it! If you guys have more ideas on how to get my sheep spell to work, I would love that too!

 

For reference, here is the code that I currently have for my spell script:

 

scn SheepsRUsScript
ref target
begin ScriptEffectStart
set target to getself
if( target != player ) && ( target.IsActorEvil ) ;This isn't the issue, I made another spell with this setup and that one has no problems.
target.PlaceAtMe 000151DD
target.Disable
endif
end
Link to comment
Share on other sites

I figured out the issue! You can use PlaceAtMe on other actors! The issue was in the if statement. I commented out everything after 'if( target != player)' and it worked! Yay for sheep!

 

I would still like to know if there is a way to tell if an actor is an enemy or not, though. This would help, because then friendlies could not get hit by this.

 

Thanks everyone!

Link to comment
Share on other sites

Unfortunately I cannot comment on the PlaceAtMe aspect because it has been the subject of some debate as a function (it has been argued that overusing PlateAtMe might cause 'bloat' in the long term). Hopefully someone else can give you some more ideas on how to maybe avoid that. :blush:

 

It is possible to use the editor ID of an object in a script. If the sheep has a form ID of 000151DD (the one in your script) and an editor ID of "Sheep" (I have no idea what it really is, you should check it before typing anything), then just using the editor ID "Sheep" in the script would be enough. The object (Sheep) can be renamed after the script has been compiled, but it will not effect the already compiled script, so I suspect the name is converted to the form ID when compiling the script. But when writing the script, it makes the script more readable to use the editor ID and not form ID. For example to add a weapon to a character, one could use:

SomeActorRef.AddItem WeapIronDagger 1

As for the script, magic effect scripts are run on the target actor: casting a spell with a custom script effect on an NPC will have the script run on that NPC, just like an object script would. It is therefore possible to just use a function that needs to be run on a reference without typing the reference, because the game will consider the current NPC (that the script/effect runs on) as that reference, when the reference part is omitted in the script! Handy, some might argue. :smile:

 

The IsActorEvil function returns true for actors that are only in evil factions and not in a single non-evil faction, so that might explain why the condition check never returned true. Maybe something like a vampire or a bandit would qualify as an evil actor, but guards or other civilians would probably not. Also, the wiki page says no creatures are considered evil, so that might also explain something.

 

I have never had to quickly identify an enemy of the player and the allies of the player, but maybe something like the GetCombatTarget function, combined with GetAllies and an ar_Find would work? Below is a small untested idea, for the spell effect script. I have no idea if it compiles, although I think it should, but to give an idea of what to maybe try. Again, the PlaceAtMe part would need someone else to present some thoughts, I cannot comment on it, I have left it there because you had it in your script.

scriptname SheepStaffScript

array_var PlayerAllies
ref CombatTarget

begin _ScriptEffectStart

    ; this assumes the PLAYER is using the staff and not any other
    ; actor like a follower or somesuch

    if eval ( ( GetIsReference PlayerRef ) || !( PlayerRef.IsInCombat ) || ( IsEssential ) )
        ; feel free to add any extra conditions here
        return
    endif

    let PlayerAllies := PlayerRef.GetAllies
    let CombatTarget := GetCombarTarget

    if eval ( ( ar_Find CombatTarget PlayerAllies ) != ar_BadNumericIndex )
        PlaceAtMe Sheep 1
        ; Disable --> are there any other options ???
    endif

    ; OBSE should automatically destroy unreferenced arrays,
    ; (unlike string_vars), but it does not hurt to manually
    ; set PlayerAllies to ar_Null before the script terminates

end

The example assumes you have run the CS with OBSE through "obse_loader.exe -editor" or that you use the Construction Set Extender by shademe. If you do not use the CSE, it might be worth taking a look at it! OBSE allows for the use of function return values directly in various places (like an array index):

let ValFromSomeIndex := SomeArray[(SomeFuncThatReturnsNumber SomeArg SomeArg2)]

So it might be possible to write the condition check in the example idea like this, too:

scriptname SheepStaffScript

begin _ScriptEffectStart

    ; this assumes the PLAYER is using the staff and not any other
    ; actor like a follower or somesuch

    if eval ( ( GetIsReference PlayerRef ) || !( PlayerRef.IsInCombat ) || ( IsEssential ) )
        ; feel free to add any extra conditions here
        return
    endif

    if eval ( ( ar_Find ( GetCombarTarget ) ( PlayerRef.GetAllies ) ) != ar_BadNumericIndex )
        PlaceAtMe Sheep 1
        ; Disable --> are there any other options ???
    endif

end

Hopefully that helps a bit. :thumbsup: And hopefully someone else has a better idea of whether using PlaceAtMe is smart in this specific case. Maybe restricting the number of sheeps and affected NPCs to one, and allowing only one NPC to be turned into a sheep at a time, for the duration of the spell only, would help both prevent accidentally disabling NPCs relevant to a quest and to help avoid PlaceAtMe completely. The requirement for player to be the one to use the staff/spell/something is also interesting, but I cannot remember any quick way to dynamically get the actor who has cast a spell. In Skyrim, it is passed as an argument to the script effect start event, but in Oblivion, I do not think there is a way to check the caster in an easy way... or maybe there is something I cannot remember... ? Would not be the first time. :tongue:

 

Also, have you looked at the Wabbajack script in the game? That might also be handy, I think it was implemented as a script in the game.

Edited by Contrathetix
Link to comment
Share on other sites

in my experience to check player's foe is a bit complicated...

this script below can check hostility towards pc but not that effective, nice NPC will always return negative values

if target.GetShouldAttack PlayerRef
	printc "%n may atk pc" target
endif 

in combat, the best way to check whether npc is hostile to player or not, use this

if eval(ar_Find PlayerRef target.GetTargets) > -1
	printc "%n is pc foe" target
endif 

but when the npc is NOT in combat, you can check them like this. AFAIK actors that have confidence less than 36 will run from combat

if target.GetDisposition PlayerRef <= target.GetAV Aggression - 5 && target.GetAV Aggression > 5 && target.GetAV Confidence > 35
	printc "%n is hostile towards pc" target
endif

as for your sheep case

I think this script below should be enough

if target.GetDisposition PlayerRef <= target.GetAV Aggression - 5 && target.GetAV Aggression > 5 || eval(ar_Find PlayerRef target.GetTargets) > -1
	printc "%n is hostile towards pc" target
endif 

don't worry about PlaceAtMe on actor, because when the cell reset routine kick in the reference will be gone for good

PlaceAtMe only become harm on savegame when used on objects

but the problem in your mod is ... I think the turned NPC can't go back to original. is that intentional ?

Edited by lubronbrons
Link to comment
Share on other sites

<snip>

 

Thank you! Using PlayerRef with GetTargets on the spell target saves a function call in the condition check! Also, I had no idea disposition and aggression were connected like that. Every day one learns something new. :happy:

 

Also, now that I remember it, the thread by QQuix about his research on PlaceAtMe a while ago is here, if it helps: Cell Reset

Edited by Contrathetix
Link to comment
Share on other sites

 

Thank you! Using PlayerRef with GetTargets on the spell target saves a function call in the condition check! Also, I had no idea disposition and aggression were connected like that. Every day one learns something new. :happy:

Also, now that I remember it, the thread by QQuix about his research on PlaceAtMe a while ago is here, if it helps: Cell Reset

 

 

your welcome Contra :) it is great to see you still doing Oblivion troubleshooting here~

yeah...

aggression, disposition, and confidence is variable that affecting hostility towards pc

Link to comment
Share on other sites

Thank you! Yes, I am still here and I am not going to go anywhere anytime soon, either. :smile: The plan is to remain here for the foreseeable future and to continue my mod projects for Oblivion when I find the time (a bit busy at the moment, I have not had the time for modding). There is something about Oblivion that Skyrim or other titles do not have, but I cannot quite point out what it is.

 

Also, if you do not mind, just to quote this part again from your previous post, which is extremely relevant to the whole sheep transform spell thingy:

 

--

but the problem in your mod is ... I think the turned NPC can't go back to original. is that intentional ?

 

Which means that, for example:

  • If the NPC or creature is a questgiver or otherwise needed for a quest alive (such as for dialogue), then the NPC or creature will no longer be available if it is just left disabled. Probably not an issue for hostile NPCs, but one can never know (for example, if using a mod that allows one to join an evil faction that can give quests, with the faction being hostile at first, it would be possible to disable the quest givers in that faction when they are hostile, for example before the player joins the faction).
  • If the NPC or creature has to be killed for some reason (to advance a quest, for example), then killing them is not possible anymore when/if the actor is disabled and replaced with a sheep (which would be sort of funny, but then again, it would leave the quest stuck). Killing the sheep would still leave the original NPC disabled but alive, unless some sort of workaround would be implemented to kill the NPC if the sheep is killed.
  • Essential NPCs (if there are any essential NPCs hostile towards the player somehow???) probably should not be turned into sheep that can be killed by the player, because it would defeat the purpose of marking the NPCs as essential, when the player could remove them from the gameworld forever by using the staff on them.
  • If the NPC or creature has an item in their inventory that the player would need to fetch, then the item would be become unavailable when the original actor is disabled, unless the inventory of the actor (including leveled lists) is transferred to the sheep (or the sheep is turned into a sort of scripted proxy activator for accessing the original NPC's inventory, but I do not know if it is possible to activate a disabled NPC - if not then the inventory would need to be moved to the sheep somehow).
  • Maybe something else, too, that I cannot think of at the moment.

Just to clarify the issue to TheManWithoutAPlan. :smile: Also a happy new year to you, L! May it be better than the previous one.

Edited by Contrathetix
Link to comment
Share on other sites

Happy new year to you too Contra and best of luck to all of us and around you too !!!

 

that's right

it will trouble some NPCs quest related, it will make the game unstable in many ways

I think the script need to turn back the NPC to original

also make sure your spell have time effect something like 30 seconds or whatever second you want

scriptname SheepStaffScript

ref theSheep

begin ScriptEffectStart
	if GetIsReference PlayerRef ;this line same as -> target != player, but more faster
		;prevent player from getting turned into sheep
		Dispel SheepStaffSpell
		return
	elseif PlayerRef.IsInCombat
		;prevent sheep spell when player is in combat
		Dispel SheepStaffSpell
		return
	endif

	if GetDisposition PlayerRef <= GetAV Aggression - 5 && GetAV Aggression > 5
		;only hostile actors that get turned into sheep
		Let theSheep := PlaceAtMe Sheep 1
		Disable
	else
		Dispel SheepStaffSpell
		return
	endif

end

begin ScriptEffectFinish
	;if you set script time effect 30 secs, then at the end of spell effect the actor will turn back to original
	if theSheep
		theSheep.Disable
		Enable
	endif
end
Edited by lubronbrons
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...