Sign in to follow this  
Box

A challenging problem for fellow scripters

Recommended Posts

One of the things I would like to do for a mod I'm working on is have non-droid units use special weapons like the flamethrower and carbonite emitter. The first problem with this, as far as I can see, is that when it comes to targeting enemies human characters use force powers in the spot where droids use item spells. So I've created a flamethrower item that can be equipped by both humans and droids but only one of them can use it to target enemies.

 

There are some ways around this. I looked at a mod that implemented a flamethrower for human characters. Instead of targeting an enemy, the flamethrower would targeting the user like an energy shield. Then the script that resolves the spell finds an enemy near the user to fire the flamethrower. This is pretty clever, but I don't like it as a solution because you can't choose who to target.

 

So I had another idea. I would simply create a force power called "Use Item". The power would activate a script that would find the item equipped on the armband and then activate it. This is where I'm having some trouble. I've created the following script and hooked up everything so it runs, but it doesn't activate the item.

//:: k_sup_useitem

// Custom script by Box
// This is a script for using a custom weapon from a spell
// This could be considerably more tricky

#include "k_inc_debug"

void main()
{
	object oItem;		// The item to use
	int nInventorySlot;	// The inventory slot where we're keeping the item
	event evItem;		// Event for activating item?
	object oTarget;		// Item target
	location lTarget;	// Item target location
	
	// Get the item we're trying to activate
	// This seems pretty simple so I imagine it works
	nInventorySlot = INVENTORY_SLOT_LEFTARM;
	oItem = GetItemInSlot(nInventorySlot, OBJECT_SELF);
	
	// Activate the item obtained
	// Not sure exactly what is going on here with "events"
	oTarget = GetSpellTargetObject();
	lTarget = GetSpellTargetLocation();
	evItem = EventActivateItem(oItem, lTarget, oTarget);
	
	// I'm guessing this is what we need to run next
	// If the last block returned an event for activating an item, this should perform the event and activate the item, right?
	SignalEvent(OBJECT_SELF, evItem);
}
I've never written a script like this using "events" before. I just found functions in the documentation that seemed like they would do what I wanted. Unfortunately while I can verify that the script is called, it doesn't actually activate the item. I don't know if there are only certain items that can be activated. Most consumable items seem similar in their .uti files with a property that determines what spell is cast when the item is used. I was assuming that an event activating an item would work similarly, but I can't even get this to activate a regular energy shield.

 

On the other hand, I've considered a completely different approach. Instead of trying to activate the item from a script, I would instead just determine the identity of the item equipped and then perform the effect of the item right in this script. There's a problem with that though. I've been using weapons and energy shields with a cooldown effect, so instead of having 5-10 uses before disappearing, they have unlimited uses but can only but have to wait 60 seconds before being used again. If I bypass actually activating the item with this script, then I need to figure out a way to implement a cooldown system. I have no experience doing anything like that. I assume it would probably involve global variables and heartbeat scripts but I don't know where to start.

 

So that's my situation. I think it's a pretty interesting problem and it would be really cool if we could figure it out. What do you guys think? Does anyone know how in-script item activation or cooldowns work? Or maybe you guys have a different way of looking at this problem.

Share this post


Link to post
Share on other sites

You shouldn't have to go through all if this trouble. You should be able to set a spell to be used on item activate. Check out Mira's Rocket Laincher item for reference.

Share this post


Link to post
Share on other sites

You shouldn't have to go through all if this trouble. You should be able to set a spell to be used on item activate. Check out Mira's Rocket Laincher item for reference.

 

I appreciate the help, but I'm going to need you to be a little more specific. I've looked at Mira's wrist launcher .uti file and it has no properties, simply referencing the base item. I have to admit I don't really understand how the wrist launcher base item works. Actually I'm pretty new to spell mods in general, but I've spent some time getting to know how they work.

 

FWIW, I understand that you can have a human character activate a self-targeting spell with an item, like an energy shield. I just don't know how to do it with enemy-targeting items like a flamethrower.

Share this post


Link to post
Share on other sites

I have to say, I think I've really outdone myself this time. My solution to this might be the highest point of my TSL modding career.

Share this post


Link to post
Share on other sites

So there is a similar property you can set that works to attack hostiles.  I suppose the big issue is getting it to work with droids and humans though, right?

Share this post


Link to post
Share on other sites

I'm still working out the details at the moment. The solution is really more cleverness than learning anything new. I want to write it out in full detail though for the benefit of people like me who try to learn to mod by looking up stuff on forums like these.

 

Basically you have to work with two items that use two different spells, an equippable wrist launcher and a separate ammo item.

Share this post


Link to post
Share on other sites

Hey it's not dreadful. It took a lot of effort and creativity on my part.

 

Tomorrow I'll make a "guide" on how to do this.

 

BTW, what was your original idea?

Share this post


Link to post
Share on other sites

Sorry, I didn't mean to say your idea was dreadful. I'm not sure what I was even looking at to be honest...

 

Didn't really have an idea, so I'm looking forward to yours!

Share this post


Link to post
Share on other sites

Okay here's what I was able to accomplish. Like I said, I'm writing this for the benefit of aspiring modders who may come and read it later. So I'm going into a bit more detail not because I think you guys don't know most of this stuff already, but because some people don't and that information deserves to be shared.

 

First of all, you can't fight the UI. Hostile spell targeting has 3 sections on the UI which I'm sure you're all familiar with. The first section is populated by feats, the third is populated by inventory, and the second depends on whether the user is a human or a droid. For humans, the second section is populated by force powers and for droids, it's populated by equipment. As far as I know, there's no way around this. It does mean that you can do some pretty cool things for droids though. For example, you can have a grenade launcher weapon that fires like a normal blaster but also lets you activate grenades. The same item, though, won't provide grenades for humans because you can't actually select weapon from the UI.

 

Anyway, after Varsity suggested looking at the wrist launcher, I remembered that inventory spells were a way to target enemies. In game, grenades are generally what you're dealing with but you can fire any spell you want from inventory. The problem here is that inventory is shared between everyone so you might have a flamethrower item but anyone can use it as long as they've equipped it. I came across 2 ways to restrict who can use inventory spells though. The first way is that you can actually use regular equipment restrictions to restrict spell activation. Basically, you can have a grenade that's only useable by characters with a certain feat or with a certain light/dark alignment. They appear as selectable in the inventory but they don't actually do anything. The second way of restricting access to inventory is to use rockets. Rockets can only be used by characters with a wrist launcher. And unlike before, rockets don't appear in the inventory of characters without wrist launchers. Unfortunately, as far as I know, there is only one type of wrist launcher and one type of rocket which means that all wrist launchers and all rockets are cross-compatible.

 

Okay, putting it all together now. The goal here is to create an item that works like a flamethrower for humans. Basically, this item would do nothing until you equipped it. Once equipped, it would give the person equipping it the ability to shoot flamethrower blasts at regular but restricted intervals. No consumables would be spent but access to the flamethrower would not be restricted in some way to discourage spamming it each turn.

 

The way that I did this is by creating two items with two different spells. The first is an equipable wrist launcher item that acts as the flamethrower itself. To this wrist launcher, I add the ability to activate a self-targeting spell. It's similar to an energy shield. The wrist launcher runs a custom script that I've called "reload". Basically what it does is it adds an ammunition item to the inventory. The ammunition item is a one-time consumable rocket that fires the flamethrower spell on activation. The reload script first checks to see whether there exists an ammunition item in inventory before adding it. To limit the use of the flamethrower to only the person who reloaded it, a special prerequisite feat is put on the rocket. This same feat is granted by the wrist launcher that produces the rocket. So only the character with the flamethrower equipped can fire it and characters without wrist launcher items equipped won't even see it on the UI.

 

This approach has a number of benefits. The first is that we can regulate use of the flamethrower by regulating how many times the wrist launcher can be activated. It's possible to only allow reloading 1 time per minute which means no more than 2 uses of the flamethrower can be stored up as once. I, however, preferred to extend the reloading script to do a 9 second animation in order to make an interesting tradeoff between reloading for another shot or using a primary weapon. The other benefit is that any spell activated by a rocket item when a wrist launcher is equipped uses the wrist launcher animation before firing the script. This isn't a big deal for flamethrowers, but some spells like grenades don't activate their scripts until they've blown up. So if we wanted to create a grenade launcher item in a similar manner, this allows us to keep the correct animation.

 

There are some drawbacks to this approach however. The first has to do with the ammunition. If you have two characters with the same exact type of flamethrower equipped, they share ammo. That means that one person can reload allowing the other to fire. There is a potential solution to this, though. You could simply create one type of flamethrower ammo for each party member whose activation is restricted to that party member. But that can potentially clutter up the UI as more characters use the weapon. The second limitation has to do with the slight difference between arm bands and wrist launchers and how they activate spells. Wrist launchers are extremely similar to arm bands but not exactly. Arm bands can only be activated as equipment. Wrist launchers can be activated as equipment or inventory. And while it's possible to restrict reloading in-script to only wrist launchers that have been equipped, unequipped wrist launchers still show up as able to be activated in the UI. This is a minor annoyance but can still be a source of confusion.

 

Anyway, I want to finish this out by posting the source code for the reload script.

//:: k_sup_reload

// Custom script by Box
// Use this script to resolve an auxiliary weapon activation

#include "k_inc_debug"

void main()
{
	// Normally there would be some logic to determine this string but for now we're just using a test
	string sAmmo = "testammo";
	
	// We want the weapon used to match the one equipped by the user
	object oWeapon = GetSpellCastItem();
	object oEquip = GetItemInSlot(INVENTORY_SLOT_RIGHTARM);	// I plan to restrict auxiliary weapons to right arm only
	
	// We can use this to compare objects by exact match
	if (oWeapon == oEquip) {
		
		// Before adding the ammo, we have to check if one already exists
		object oAmmo = GetItemPossessedBy(OBJECT_SELF, sAmmo);
		// When oAmmo returns as null, that means we don't have ammo and should add it
		if(!GetIsObjectValid(oAmmo)) {
			
			// Add the ammo
			CreateItemOnObject(sAmmo, OBJECT_SELF, 1, 1);
			
			// For the animation, we want to entangle the user to keep him/her from escaping the reload time
			effect eStop = EffectEntangle();
			ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eStop, OBJECT_SELF, 9.0f);
			
			// These two animations are meant to kind of look like reloading
			DelayCommand(0.0f, AssignCommand(OBJECT_SELF, ActionPlayAnimation(10035, 1.0f, 8.0f)));
			DelayCommand(8.0f, AssignCommand(OBJECT_SELF, ActionPlayAnimation(10038, 1.0f, 1.0f)));
			
			// I would add sound effects here but I'm not sure how to have them loop for 9 seconds at the moment
		}
	}
	
}


A quick final note about the reloading animations. In order to get the animations to work properly, I had to set the casttime column to 0 in the spells.2da table where I created the spell that runs this script. Wrist launchers want to use the standard force animation where the character sticks his/her arm out. Setting the cast time to 0 cancels this and goes straight into the animations in-script.

Share this post


Link to post
Share on other sites

So I thought I was onto finding a yet better way to do this using custom fields that you can set on objects in-script. Unfortunately, my computer has been having trouble running TSL and recently has been crashing so I'm not going to be able to do a whole lot of modding for a while. Someday, maybe I'll be able to really nail this.

Share this post


Link to post
Share on other sites

I haven't tested it yet but this is my new idea:

 

-Create auxiliary weapons as wrist launchers, have them grant one of 3 types of feats: weapon, grenade, or rocket, each calls a reload spell

-Create 3 reload spells: reload, reload grenade, reload rocket, different spells are for different types of weapons

-Create 3 types of 'ammo' items as rockets: use weapon, use grenade, use rocket, all are single use, each call a use weapon spell on use, each 'ammo' requires one of the 3 feats: weapon, grenade, or rocket

-Create 3 use weapon spells: use weapon, use grenade, use launcher

-For each type of ammo, permute across each character so we have 3 types of 'ammo' items for each character, i.e. use weapon (Atton), use grenade (Atton), use rocket (Atton) for each character

-In the reload scripts, simply spawn the correct 'ammo' item for the reloading character into the inventory if it is not available, no waiting time or reload animation, also set a predesignated "Reload" local boolean on the item to true

-In the use weapon scripts, run two separate scripts, first run the script to do the effect of the appropriate weapon equipped iff the "Reload" local boolean is set to true and then set it to false, then after 20 seconds run the reload script

 

It's not perfect but it's maybe the best I can come up with that reduces UI clutter and can't be exploited in game

 

The only thing I'm not sure about yet is if it's totally necessary to make the weapons wrist launchers instead of armbands. Armbands would be less screen clutter but I would have to find somewhere else to equip a wrist launcher.

Share this post


Link to post
Share on other sites

This could all be made to be a lot simpler if I could find a way to shoot projectiles in-script.

 

Anyone know how to do that?

 

My current ideas:

1) Spawn an invisible creature and have it cast a fake spell at the location of the target and define the projectile in the spells.2da line

2) Create a beam effect that somehow mimics a projectile being fired

 

I don't think I have the energy to really pursue either of these unless someone here knows about what would be involved.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this