Need help with...
#1
Posté 19 janvier 2012 - 10:31
This script below. I wanted to convert it to an onactivated script through conversation to an npc, versus using an object. What needs to change in order for it to target the player over it firing on the npc speaker?
Secondly,
I need a script that will lock a transition until it is used from the other side. Additionally, have that script remove a placeable object from being in front of the intended transition.
And thirdly:
A script that attatches to an item as a useitem unique.. that when used on a target placeable will remove it, and play a vfx or two.
void main()
{
object oPC = GetLastUsedBy();
object oSelf = OBJECT_SELF;
object oItem = GetFirstItemInInventory(oPC);
effect eEffect = EffectVisualEffect(VFX_FNF_HOWL_WAR_CRY_FEMALE);
if (GetGold(oPC) >= 1000)
{
// If Player has 1k Gold
while (GetIsObjectValid(oItem)==TRUE)
{
SetIdentified(oItem,TRUE);
oItem = GetNextItemInInventory(oPC);
}
DelayCommand(1.0, AssignCommand(oPC, TakeGoldFromCreature(1000, oPC, TRUE)));
DelayCommand(1.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, eEffect, oPC));
}
if (GetGold(oPC) <= 1000)
{
// If Player does not have 1k gold
AssignCommand(oSelf, SpeakString("You'll need more gold my friend!", TALKVOLUME_TALK));
}
}
#2
Posté 19 janvier 2012 - 10:46
In this case, use:
object oPC = GetPCSpeaker();
instead of:
object oPC = GetLastUsedBy();
As for the other requests, they would take a bit more effort than I have time for right now.
The transition will probably work best by checking for a variable on the PC and only transporting them if that var exists.
Set the var on them when they use it from the first side.
The 3rd script would take a few more lines of code to handle the vfx.
Have you tried using one of the script generators to help you learn how to code?
http://nwvault.ign.c....Detail&id=1502
That may be able to handle most of the more basic scripts like this.
Modifié par wyldhunt1, 19 janvier 2012 - 10:48 .
#3
Posté 19 janvier 2012 - 11:50
#4
Posté 20 janvier 2012 - 12:14
The Vault has a series here: http://nwvault.ign.c...ripting/course/
Or, this thread has a big list of useful stuff: http://social.biowar...-3254065-1.html
Once you understand the very basics of what a variable is and the basic structure of the code, a script generator may be the next best step. Its examples will answer a lot of your questions about how to do stuff.
It's a lot easier than people usually assume once they understand the language structure.
Variables are references that you can call repeatedly in a script without having to worry about typos or making the engine re-check the same thing over and over.
int tells the engine that you are defining a new variable, and that variable is an integer (A whole number).int nSomeNumber = 10;
nSomeNumber is the name that you've given the variable. You can use any name you want. Just don't use the same name twice in the same function.
= 10 is the value that you are using for nSomeNumber. In this case, 10.
; is used like a period in code. You place a ; at the end of every statement to let the engine know where the end of the statement is at.
So, a translation of the above line would be:
I am declaring a new integer variable named nSomeNumber and it is equal to 10.
Once a variable is defined, you can use the name that you chose anywhere in the function and the engine will know to replace your variable name with the variables value.
So, I could say:
if (nSomeNumber > 0)
{
string sSomeText = "Some Number is positive.";
}
The line if (nSomeNumber > 0) is checking to see if the variable nSomeNumber is greater than (>) the number 0.
That line reads out almost like English. "If the variable nSomeNumber is greater than zero"
You'll notice that the code under it is wrapped in curly brackets. IE { and }.
These are used to separate a block of code from the rest of the code.
The "if" statement ran a check to see if something was true. The code in the curly brackets under it will only run if that check returns true. If it returns false, everything inside of the { } will be ignored.
Thus, our final sentence for that block of code would look something like:
If the variable named nSomeNumber is greater than 0, then declare a new string variable named sSomeText which is equal to the value "Some Number is positive".
A couple of things to note about the line
string sSomeText = "Some Number is positive.";
Any actual text that you want to use as a text string in game will need parenthesis around it (").
Note the ; at the end of the line.
You can also store variables on objects to use later in some other script.
You could do something like:
object oPC = GetEnteringObject();
SetLocalInt(oPC, "TriggerCheck", 1);
on an On Enter of a trigger.
That would store an int variable on the oPC object. The variables name is TriggerCheck. The value is equal to 1.
Now, in an entirely different script, you could use:
object oPC = GetEnteringObject();
if (GetLocalInt(oPC, "TriggerCheck") == 1)
{
//Add code here to transport the player
}
Note that oPC is actually a variable (of the "object" type) that we defined on the first line.
oPC is equal to whatever is returned by the GetEnteringObject() check.
By using oPC as an object variable, we only have to check to see who is entering the trigger once. After that, oPC will always call that same object.
The code block above will read much like in English:
If we can get an integer variable off of the oPC object named TriggerCheck with a value equal to 1, then run code to transport the player.
Modifié par wyldhunt1, 20 janvier 2012 - 12:50 .
#5
Posté 20 janvier 2012 - 12:17
#6
Posté 20 janvier 2012 - 01:03
It is the most complete reference for finding or understanding how any of the bits of code work.
It is large enough that you may need a more basic tutorial to help you understand what you're looking at before the Lex will make a lot of sense, if you don't understand the basics of programming structure in Aurorascript yet.
It's well worth browsing though. I still keep it open while I code as a quick reference.
#7
Posté 20 janvier 2012 - 01:45
But it came out like this :
void OnActivate(object oEventItem, object oActTarget, location lActTarget, object oActivator)
{
object oTarget;
effect eVFX;
int nType;
object oPC = oActivator;
// The target must be a certain type of object.
nType = GetObjectType(oActTarget);
if ( nType != OBJECT_TYPE_PLACEABLE )
{
SendMessageToPC(oActivator, "Improper use of this item!");
return;
}
// Destroy an object (not fully effective until this script ends).
eVFX = EffectVisualEffect(VFX_FNF_MYSTICAL_EXPLOSION);
oTarget = GetObjectByTag("Hellfiretombcover");
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oTarget);
DestroyObject(oTarget, 3.0);
}
The very first line is obviously incorrect. It should be Void main() right? So what do I do with the extra stuff on top? Moving it down a line gets it recognized as an unknow value when trying to compile it. Same for putting it under the squiggly bracket. Removing it gives me an "missing Int value"
Modifié par Foregone_Conclusion, 20 janvier 2012 - 01:58 .
#8
Posté 20 janvier 2012 - 02:05
/*
* Script generated by LS Script Generator, v.TK.0
*
* For download info, please visit:
* http://nwvault.ign.c....Detail&id=1502
*/
void main()
{
object oTarget;
effect eVFX;
int nType;
object oEventItem = GetItemActivated();
object oActTarget = GetItemActivatedTarget();
location lActTarget = GetItemActivatedTargetLocation();
object oActivator = GetItemActivator();
object oPC = oActivator;
// The target must be a certain type of object.
nType = GetObjectType(oActTarget);
if ( nType != OBJECT_TYPE_PLACEABLE )
{
SendMessageToPC(oActivator, "Improper use of this item!");
return;
}
// Destroy an object (not fully effective until this script ends).
eVFX = EffectVisualEffect(VFX_FNF_MYSTICAL_EXPLOSION);
oTarget = GetObjectByTag("hellfiretombcover");
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oTarget);
DestroyObject(oTarget, 3.0);
}
Other than that, it works perfectly!
Modifié par Foregone_Conclusion, 20 janvier 2012 - 02:32 .
#9
Posté 20 janvier 2012 - 02:32
That is valid code.
However, it won't do anything by itself.
As you guessed, you need a void main().
That code is a custom function.
If you read any of the tutorials, they'll get in to that and explain it better than I could do here.
void is a key word that tells the engine that you are defining a new function.void OnActivate(object oEventItem, object oActTarget, location lActTarget, object oActivator)
OnActivate is the name of the new function (It can be any unique name, much like the name of a variable.).
The stuff inside of the brackets ( and ) is a list of information that the function requires in order to work properly.
In this case, you need to give the function the following list of stuff:
An object that the function can use for the oEventItem variable. (Probably the item used)
An object that the function can use for the oActTarget variable. (Probably the target of the item used)
A location that can be used for the lActTarget variable. (Probably the target location of the item used)
An object to be used for the oActivator variable. (Probably the object that used the item)
Once a function has been defined, you can use the function in your script by calling the function name and feeding it all of the info that it needs.
A finished script using this function might look like:
void OnActivate(object oEventItem, object oActTarget, location lActTarget, object oActivator)
{
object oTarget;
effect eVFX;
int nType;
object oPC = oActivator;
// The target must be a certain type of object.
nType = GetObjectType(oActTarget);
if ( nType != OBJECT_TYPE_PLACEABLE )
{
SendMessageToPC(oActivator, "Improper use of this item!");
return;
}
// Destroy an object (not fully effective until this script ends).
eVFX = EffectVisualEffect(VFX_FNF_MYSTICAL_EXPLOSION);
oTarget = GetObjectByTag("Hellfiretombcover");
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oTarget);
DestroyObject(oTarget, 3.0);
}
void main()
{
OnActivate(GetItemActivated(), GetItemActivatedTarget(), GetItemActivatedTargetLocation(), GetItemActivator());
}
Notice the void main() at the bottom that calls the function and gives the function all of the info that it needs.
Generating custom functions seems like it may be a bit much for novice scripters to handle. I'm not sure why it would be giving you custom functions without the void main() to call the function to make sure that it works for you.
Glad to see you got it figured out though.
#10
Posté 20 janvier 2012 - 02:35
Try adding a delay to when it gets destroyed, like so:
Actually, no... It is delayed. Didn't notice that... I'll update if I see anything else obvious./*
* Script generated by LS Script Generator, v.TK.0
*
* For download info, please visit:
* http://nwvault.ign.c....Detail&id=1502
*/
void main()
{
object oTarget;
effect eVFX;
int nType;
object oEventItem = GetItemActivated();
object oActTarget = GetItemActivatedTarget();
location lActTarget = GetItemActivatedTargetLocation();
object oActivator = GetItemActivator();
object oPC = oActivator;
// The target must be a certain type of object.
nType = GetObjectType(oActTarget);
if ( nType != OBJECT_TYPE_PLACEABLE )
{
SendMessageToPC(oActivator, "Improper use of this item!");
return;
}
// Destroy an object (not fully effective until this script ends).
eVFX = EffectVisualEffect(VFX_FNF_MYSTICAL_EXPLOSION);
oTarget = GetObjectByTag("hellfiretombcover");
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVFX, GetLocation(oTarget));
DestroyObject(oTarget, 3.0);
}
EDIT: Updated to trigger the effect at the objects location instead of on the object itself.
Modifié par wyldhunt1, 20 janvier 2012 - 03:05 .
#11
Posté 20 janvier 2012 - 02:54
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oPC); Since the target is being destroyed it doesn't execute the vfx I guess.
#12
Posté 20 janvier 2012 - 03:04
Since the location of the object should stay the same even if the object is destroyed, I think it'll work as you wanted.
I'm at work right now, so I can't try to compile it or anything.
If I made a typo, let me know.
The only line I need to change is:
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oTarget);
I'll put a note to let you know when it's updated.
EDIT: Done
Modifié par wyldhunt1, 20 janvier 2012 - 03:05 .
#13
Posté 20 janvier 2012 - 10:14
But a quick question, I have a number of Onequip scripts now for items. One problem I'm running into is that they are firing when picked up,OnAcquire instead of OnEquip. The script fires when equipped still however. Also, the effects of the script don't remove after the item is dropped from inventory, and the effects even stack up multiple times. Which is obviously a problem.
This script here, being an example of one :
void main()
{
effect eEffect;
effect eVFX;
object oEventItem = GetPCItemLastEquipped();
object oEquippedBy = GetPCItemLastEquippedBy();
object oPC = oEquippedBy;
// Apply some visual effects.
eVFX = ExtraordinaryEffect(EffectVisualEffect(VFX_IMP_AURA_HOLY));
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eVFX, oPC);
eVFX = EffectVisualEffect(VFX_FNF_DISPEL_DISJUNCTION);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oPC);
// Apply some effects.
eEffect = ExtraordinaryEffect(EffectRegenerate(10, 15.0));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, oPC, 3600.0);
eEffect = ExtraordinaryEffect(EffectTemporaryHitpoints(65));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, oPC, 3600.0);
}
So I assume I need to either add another script that effects onacquire and onequip? Or is this script itself just missing the IF functions?
Modifié par Foregone_Conclusion, 20 janvier 2012 - 10:59 .
#14
Posté 20 janvier 2012 - 03:45
#include "x2_inc_switches"
void Buff (object oPC);
void Unbuff (object oPC);
void main()
{
object oPC, oItem;
int nEvent = GetUserDefinedItemEventNumber();
if (nEvent == X2_ITEM_EVENT_EQUIP)
{
oPC = GetPCItemLastEquippedBy();
oItem = GetPCItemLastEquipped();
// This is assigned to the item so you can remove the effects on unequip.
AssignCommand (oItem, Buff (oPC));
}
else if (nEvent == X2_ITEM_EVENT_UNEQUIP)
{
oPC = GetPCItemLastUnequippedBy();
oItem = GetPCItemLastUnequipped();
// Assigned so the item is OBJECT_SELF, for easier creator checking.
AssignCommand (oItem, Unbuff (oPC));
}
else if (nEvent == X2_ITEM_EVENT_ACQUIRE)
{
oPC = GetModuleItemAcquiredBy();
oItem = GetModuleItemAcquired();
object oOldOwner = GetModuleItemAcquiredFrom();
}
else if (nEvent == X2_ITEM_EVENT_UNACQUIRE)
{
oPC = GetModuleItemLostBy();
oItem = GetModuleItemLost();
object oNewOwner = GetItemPossessor (oItem);
}
else if (nEvent == X2_ITEM_EVENT_ACTIVATE)
{
oPC = GetItemActivator();
oItem = GetItemActivated();
object oTarget = GetItemActivatedTarget();
location lTarget = (GetIsObjectValid( oTarget) ? GetLocation( oTarget) : GetItemActivatedTargetLocation());
}
}
void Buff (object oPC)
{
effect eEffect1, eEffect2, eVFX, eDur, eLink;
eVFX = EffectVisualEffect(VFX_FNF_DISPEL_DISJUNCTION);
eDur = EffectVisualEffect(VFX_IMP_AURA_HOLY);
eEffect1 = ExtraordinaryEffect(EffectRegenerate (10, 15.0));
eEffect2 = ExtraordinaryEffect(EffectTemporaryHitpoints(65));
eLink = EffectLinkEffects (eEffect1, eEffect2);
eLink = EffectLinkEffects (eLink, eDur);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, 3600.0);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oPC);
SetLocalInt (OBJECT_SELF, "BUFFED", TRUE);
}
void Unbuff (object oPC)
{
effect eEffect = GetFirstEffect (oPC);
while (GetIsEffectValid (eEffect))
{
if (GetEffectCreator (eEffect) == OBJECT_SELF)
{
RemoveEffect (oPC, eEffect);
}
eEffect = GetNextEffect (oPC);
}
SetLocalInt (OBJECT_SELF, "BUFFED", FALSE);
}
You need to create the effects in an assigned subroutine so you can make the item the effect creator. That allows you to check against that item when it's unequipped to remove only the effects it made.
I used a variable check for simplicities sake, but a loop through the effects present on the PC to see if any of them have been created by that item would be slightly more reliable.
Hopefully this quick tag framework will be of use to you for your other scripts. If they're the same sort, buff on equip/remove effects on unequip, you'd just need to change the effects in the Buff script.
#15
Posté 20 janvier 2012 - 09:22
There are a few tutorials on tag based scripting in one of my links in an earlier post, which I advise you to read because tag based scripting is important to understand.
The basic idea is that your module event scripts which deal with items will have a small block of code that executes a script with a name equal to the item’s tag.
So, if an item has a tag of “MyItem”, then a script named “myitem” will fire every time ‘any’ event happens concerning that item.
In the item’s script, you need to control which part of the script fires for each event.
If you look at the example that Failed.Bard posted, you’ll see that it is divided up in to sections.
Each section begins with an int variable which represents the number of the event that just triggered.
Under that, there is a block of code wrapped in curly braces { }.
The code in the curly braces will only run if the event that triggered is equal to the event named above the curly braces.
Each of these events already has some default variables defined so that you know how to define things such as the item or the character using the item.
By using this template, you can have an item that does something different for each event.
In this case, Failed.Bard added code to the X2_ITEM_EVENT_EQUIP block of code and the X2_ITEM_EVENT_UNEQUIP block of code.
The other blocks of code are still empty. All they do is define a few variables and then never do anything with them.
If you need help deciphering any of it, let me know.
Modifié par wyldhunt1, 20 janvier 2012 - 09:32 .
#16
Posté 20 janvier 2012 - 09:50
And thanks for some more feed back and the help prior to now Wyld. I can understand it well enough. A lot of the functions by name alone are pretty self explanatory. I'll read the tutorials again now that I'm not running on so little sleep!
I know how tag based scripting is supposed to work, but I didn't know that placing the code IN the script was a way to make it function as intended. Just little things I didn't know that make a difference. Also the script generator doesn't include things like this unless you go well out of the way to make sure its there, but like I said, still a lot of things I didn't know!
But thanks for the patient and very helpful replies so far! Learning experience I've been trying to get into for a long time!
#17
Posté 20 janvier 2012 - 10:00
I apologize if my responses are way too basic. Since I don't know how much you know, I tend to start at 0 just to make sure. That, and someone else may find this thread later who may be at the very beginning.
#18
Posté 23 janvier 2012 - 12:11
But I don't even know where to start on something like this. Any advice?
#19
Posté 23 janvier 2012 - 03:35
Foregone_Conclusion wrote...
So I'm having a bit of trouble understanding the IF functions and just exactly what can be done with them. Right now I was trying to come up with a template for doing quests and journal entries, AND conversation options all at the same time.
But I don't even know where to start on something like this. Any advice?
Just about everything can be done with the If statment.
The First part is Probably learning what Kinds of Events exsist in the game and where you can store data at. Then writting your script often becomes as simple as saying what you want to happen. and then writting out exactly that.
example:
lets say you want a Quest that has three states.
- getting the Quest.
- fulfilling the Task.
- and Reporting back for Rewards.
that looks like you can just simply assign a number to each of the states to simply track them and place that number on the PC. To make it more human readable we can give each State a Name (label) that will be constant, something like.
const int QUEST_STARTED =1;
const int QUEST_TASK_DONE=2;
const int QUEST_FINISHED=3;
when we start out with the PC having done nothing the Quest State will not yet be defined therefore its value will be 0.
So lets add that in there as well.
const int QUEST_NOT_STARTED=0;
Hmm, we also need a name for the place we are going to Store the data, so we can find it again. Lets just call it Quest1. We will use this name for the local integer that we place on the PC to track the state of the quest.
Now, what do we want to happen. When the PC talks to the NPC we want him to Give him the Option to start the Quest. This sounds like we need a starting condition for the 'Text appears When' node for the concersation. So we know where. Now when do we want this to appear.
if the quest has not yet started then Ask the PC if he want to do the quest, If not Don't ask dont tell.
if (QuestState== QUEST_NOT_STARTED) return TRUE else return FALSE;
hmm That look good to me we just need to fill in the stuff we missed, like fetching the Quest state from where we have it stored, and making it into a starting condition. so we end up with.
const int QUEST_NOT_STARTED=0;
const int QUEST_STARTED =1;
const int QUEST_TASK_DONE=2;
const int QUEST_FINISHED=3;
int StartingConditional()
{
//Define the PC, so we can get the state off of him.
object oPC GetPCSpeaker();
// Get the current quest state from the PC.
int QuestState = GetLocalInt(oPC,"Quest1");
//Do what we said we want to do.
if (QuestState== QUEST_NOT_STARTED) return TRUE else return FALSE;
}
It would not hurt at this point to think ahead a little bit. It looks like we are going to be using thies states quite a bit. So we can move them off into an include file that we can just add to our scripts as we need them. we will call this file inc_queststates. While we are at it, It also looks like we are gong to be retriving the quest state from the PC quite a bit. So let add a function to our include to get the Quest State from the PC and make Our Script even more Human readable. with this we end up with.
////File Inc_QuestStates////////
const int QUEST_NOT_STARTED=0;
const int QUEST_STARTED =1;
const int QUEST_TASK_DONE=2;
const int QUEST_FINISHED=3;
// This is just a wraper around the GetLocalInt To amke it more readable.
int GetQuestStateFromPC(object oPC, string sQuest)
{
return GetLocalInt(oPC, sQuest)
}
With all that moved into our new include our script can now look like this.
#include "inc_queststates"
int StartingConditional()
{
//Define the PC, so we can get the state off of him.
object oPC GetPCSpeaker();
// Get the current quest state from the PC.
int QuestState = GetQuestStateFromPC(oPC,"Quest1");
//Do what we said we want to do.
if (QuestState== QUEST_NOT_STARTED) return TRUE else return FALSE;
}
Ok so we have our script for when the text is to appear to give the PC to option to start the quest. Now if he selects that option. What do we want to happen. Hmm Besides giving him more instructions in the Dialogue we just want to change the state of the quest. hmm, It would be really nice if that include also had a function to change the quest states, Sounds like that is going to happen a lot also. So lets add it to the include first.
So now our include file looks like this:
////File Inc_QuestStates////////
const int QUEST_NOT_STARTED=0;
const int QUEST_STARTED =1;
const int QUEST_TASK_DONE=2;
const int QUEST_FINISHED=3;
// This is just a wraper around the GetLocalInt To amke it more readable.
int GetQuestStateFromPC(object oPC, string sQuest)
{
return GetLocalInt(oPC, sQuest)
}
//Update the Quest state on the PC; again Just a wrapper.
int SetQuestStateOnPC(object oPC, string sQuest, int sState )
{
SetLocalInt(oPC,sQuest, sState);
}
With That in Place your action taken Script looks like this.
#include "inc_queststates"
void main()
{
object oPC = GetPCSpeaker();
SetQuestStateOnPC( oPC, "Quest1", QUEST_STARTED);
}
That is roughly what goes through my mind when i am building a quest. Righ not I am running short on time. Hope that helps to get you started.
Modifié par Lightfoot8, 23 janvier 2012 - 03:37 .
#20
Posté 23 janvier 2012 - 10:09
#21
Posté 23 janvier 2012 - 10:35
Should probably beif (QuestState== QUEST_NOT_STARTED) return TRUE else return FALSE;
if (QuestState== QUEST_NOT_STARTED) return TRUE; else return FALSE;
Should probably be:return GetLocalInt(oPC, sQuest)
return GetLocalInt(oPC, sQuest);
Modifié par wyldhunt1, 23 janvier 2012 - 11:10 .
#22
Posté 23 janvier 2012 - 11:18
Foregone_Conclusion wrote...
Thanks for that light foot. Just one thing, it doesn't want to parse the return statement on the inc_queststates.
Sorry, Wyld Got it. I was just typing the thought process. once you get the hang of it. It is not that hard. There is more to learn about how the objects intereact with there events and when they fire, then there is to learn about base scripting.
#23
Posté 24 janvier 2012 - 03:52
#24
Posté 24 janvier 2012 - 04:47
Trying to learn the order to put things in is what I had issues with too.
The only thing that really helped me was a lot of practice and a lot of studying other peoples code... and keeping the Lexicon close.
If you have any specific questions, feel free to ask them.





Retour en haut






