1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Personality Script requested by Oyster

Discussion in 'Scripts' started by Phosphorcracker, Oct 13, 2016.

  1. Phosphorcracker

    Phosphorcracker New Adventurer

    72
    0
    Nov 30, 2012
    looking for Occupation...
    Glorious Germany
    Hey there, I* made this script as requested by oyster for a personality system that would serve as conditional for certain quests he might want to design.

    http://pastebin.com/Gw4VAA4Z

    Kudosu to greatguys1

    I need to do some testing before I know for sure I didnt fudge anything up. How do I devmode ? Also how would I test this ? I make an npc with some dialogue that would call my events but how do I check if the events changed the numbers the right way ?

    *actually I had to doublecheck like everything with greatguys1 so he might aswell claim credit for it xD
     
  2. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    15,079
    54
    Apr 8, 2005
    psycho-oligist
    lost
    For information on entering ms_dev_mode and testing NPCs, read msc/test_scripts/!test_scripts_go_here.txt (in short this involves setting ms_dev_mode to 1, sticking your scripts in ms_dynamic_npc, and running the test_scripts map.)

    Also be sure to read test_scripts/Scripts_Read_Me.txt, and examine some of the examples provided in the subfolders thoroughly.

    As for your script...

    In this case, it looks as though you're trying to integrate something into the player script, so it'd go in test_scripts/player_externals.script (or, possibly, test_scripts/[map_name]/player_externals.script). Though it'd be better to process this on an NPC, so as not to add unnecessary overhead to the player script.

    The MSC Script system is case sensitive, which is among the reasons we have specific variable formats. For instance:
    Code:
    { gain_greed
    	
    	local Personality $get_quest_data(ent_me,personality)
    
    	[...]
    	
    	token.set personality 0 Greed
    Ain't gonna cut it, as "Personality" and "personality" are two separate vars.

    As a general rule, we use all caps for vars, in at least two parts separated by a underscore (eg. SOME_VAR). Since mixing data types is globally fatal, it's wise to prefix your local's with L_, globals with G_. Might be similarly wise to go a bit further, and prefix your constants, arrays, and token strings similarly, though with so many hands in the scripts, we're not always as vigilant as we should be.

    The conditional formatting in the script you linked is flawed, and liable to result in mismatched brackets on compile.

    A conditional statement with no parentheses ceases execution when it is false and jumps to the next bracket. So...
    Code:
    local L_CON1 1
    local L_CON2 2
    
    if ( L_CON1 == 1 )
    {
    	if L_CON2 == 1
    	saytext This never happens, since L_CON2 != 1
    }
    saytext We come out here.
    
    ...If there is no bracket to exit to, the event ends...
    Code:
    { check_happening
    	local L_CON "not happening"
    	if L_CON equals 'happening' //this is not true, so we stop here
    	saytext So lonely... //never happening.
    	saytext Also, not happening.
    	if ( L_CON equals 'not happening' )
    	{
    		saytext Nope, even this isn't happening, as we won't get here.
    	}
    	saytext Yet more not happening.
    }
    And of course you don't need an else statement, if you aren't going to do anything differently should the condition not be true. (Or, in this case, where it's impossible for the condition not to be true, due to the capvar right above it, there's no point in checking it at all.)

    Other than that, the script's viable, though it's not doing anything, since it never sends back the altered quest data. You could still end up with negative values or values over 100 though, despite your efforts, since your capvar statements are happening before the numbers are altered (unless you're certain that the incoming value is never greater than 1).
     
  3. Phosphorcracker

    Phosphorcracker New Adventurer

    72
    0
    Nov 30, 2012
    looking for Occupation...
    Glorious Germany
    i thought setting the token to the altered amount would update the questdata, welp going at it again...

    also I was wondering if I need the else statement but I had cases where things wont compile when there is no else to the if even if the else does nothing.

    I am sure the amount that gets added or subtracted can grow over 1 and thus the capvar, so to be clear id need to cap the var after the calculation for it to do its thing ? Also i could just assume a limit and write the if statement accordingly but could happen that ppl ignore it or dont know it better and still things go down the drain...

    So what exactly happens if I subtract below 0 ? If its just goes into normal negative numbers that wouldnt be too much of a problem.

    Code:
    { gain_greed
    	
    	local L_PERSONALITY $get_quest_data(ent_me,personality)
    	local L_GREED $get_token(L_PERSONALITY,0)
    	local L_ALTRUISM $get_token(L_PERSONALITY,1)
    
    	if ( L_GREED < 99 )
    {
    	add L_GREED PARAM1
    	subtract L_ALTRUISM PARAM1
       capvar L_GREED 1 99
    	capvar L_ALTRUISM 1 99
    
    	token.set L_PERSONALITY 0 L_GREED
    	token.set L_PERSONALITY 1 L_ALTRUISM
    }	
    }
    will this fly then ? Also I didnt find anything updating questdata, should I just use "quest set" again to update the values ? aka gif example pls. inb4 check test_scripts, I did check a couple of dozen scripts but didnt find anything with questdata

    If you say I should avoid adding stuff to the player script like the pleague Ill do that...

    PS even if i set ms_dev_mode 1 in listenserver.cfg the scripthelper keeps claiming its not, Oyster said something about a console command to be needed ?
     
  4. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    15,079
    54
    Apr 8, 2005
    psycho-oligist
    lost
    There's no pointers in MSC scripting, so no, you gotta send it back, via quest set <target> <quest_name> <data>.

    Eh... The compiler won't stop for anything, and if you're using the test_scripts system, things aren't compiled until you spawn them, and this script won't spawn on its own. So I've no idea how you made something that "won't compile". But like I said above, 1) you don't need it, and 2) your formatting is wrong so you have the mismatching brackets as a result. (and 3, you don't even need the check, in this case.)

    You capped the var between 1 and 99, so there's no need to confirm that right after, but after you add and subtract values, you'll need to cap again. Simpler to just move the cap to after the math is done, then write the token. Your token string, however, is local, and won't exist after the event is done, so nothing's happening.

    Not a problem, but it looks as though you were trying to avoid it happening with the capvar statement.

    Yes, although, again, as you're writing to a local and not the quest data or a setvard, L_PERSONALITY is going to cease to exist as soon as you exit the event. (Also, again, I don't know why you're doing this <99 check, as the result is going to be that if, for some reason, it isn't, nothing will happen.)

    locals exist only within their events (and are what you want to use when you don't need the var outside of the event).
    setvards persist throughout the entire script at run time.
    constants persist from the top script down. (But not visa-versa.)
    setvargs (globals) persist across all server-side scripts, and through crashless map changes.
    Arrays created via array.create persist across the entire script at run time.
    Arrays created via g_array.create persist across all server-side scripts.
    scriptflags persist across the entire script at run time.

    ...and while cvars can be set via with setcvar, they are generally not recommended for storing script data, and their persistence and scope varies with the cvar type. Quest data, of course, saves with the player.

    There's a few scripts in the examples with quest_data usages, including:
    example_scripts\npc\other\quest_item.script
    example_scripts\npc\sfor\wizard_base.script
    example_scripts\npc\shender_east\telf_quest.script
    reference_scripts\game_master.script (several)
    reference_scripts\monsters\base_chat.script
    reference_scripts\monsters\base_dynamic_quest.script
    reference_scripts\player\externals.script

    EditPlus has a "Find in files..." option under Search that'll let you easily search the set for scripts with specific commands (such as "$get_quest_data").

    What isn't in the test_scripts reference scripts, but probably should be, is the list of quest names already in use. That might be useful, so yar:
    Code:
    //m = destmap of last transition touched
    //d = destination spawn of last transition touched
    //mv = last gauntlet map I validly spawned in
    //dl = darkness contamination level
    //dp = damage points/1000
    //dm = last map on which dmg points were recorded
    //h = show_health toggle
    //p = health_bars toggle
    //r = ring quest stage (integer)
    //l = lighthouse keeper (spider,grave,crystal,food)
    //n = how many times name has been changed
    //s = pet pok├ęball state, 1=egged, 2=summoned [defunct]
    //f = Felwyn Symbol/Shard quest
    //b1-b9 = galat chest bank
    //a = achievments (token #0=sorc_villa)
    //rep = Got reporter reward
    //dhal = halo toggled off if set to 1
    //pnw = pet wolf name [defunt, pets see below]
    //lc = lodagond chests flag (stops repeated chest exploit)
    //sy = sylphiel's soup available
    //BODY = last submodel body layout (for char select screen)
    
    //pets = list of pet types (by script name)
    //<pet_script> = pet XP
    //<pet_script>_hp = Current Pet HP
    //<pet_script>_name = Current Name
    Well, especially since this is going to have to involve an NPC at some point anyways... For the interaction, search out game_menu_getoptions. You'll have to learn to build menus to use this eventually anyways. The first parameter of a callback from the menu will be the player ID. (Also make sure to set menu.autoopen 1 on the NPC so you can invoke his menu by simply +use'ing him.)

    Meh, it used to be that sometimes, the first time you had ms_dev_mode 1 in your listenserver.cfg, ya had to load the test_scripts map twice to get it to kick in (first by map test_scripts, then via changelevel test_scripts), though it doesn't seem to be causing that issue for me under the alpha. I'll send you some console commands, but they aren't going to be required nor useful for spawning your test scripts.

    Of course, if you're using an HLDS, rather than the listenserver, you have to put ms_dev_mode 1 in "server.cfg" instead.
     
  5. Phosphorcracker

    Phosphorcracker New Adventurer

    72
    0
    Nov 30, 2012
    looking for Occupation...
    Glorious Germany
    I never had a script giving me the error it wont compile, I had it with various other coding outside of msc that missing else statements throw odd errors for unknown reasons.

    Doing the check if its smaler 99 is just me and my weird thinking. You are right that it isnt needed theoretically but it looks odd to me when i put it away. Also its my intention that nothing should happen if its for whatever ungodly reasons not inside the intended range. Its crucial to the idea behind it that Greed is always proportional to Altruism and vice versa, if greed is 51 altruism is 49, 35 to 65 etc... also if you could escape the intended range somehow it would break the system too like if i were to just force a capvar over it it could happen that a player has 99 greed and 99 altruism. I should add some conditionals fixing it automatically, I can see that work without too much effort.

    Code:
    {
    	if ( $get_token($get_quest_data(ent_me,personality),0) == 0 ) //gets the token from the quest personality should return 0 if not assgined
    {	
    	quest set ent_me personality "50;50;50;50"
    }
    }
    {	
    	setvard DATA_PERSONALITY $get_quest_data(ent_me,personality)
    }
    
    { gain_greed
    	
    	local L_GREED $get_token(DATA_PERSONALITY,0)
    	local L_ALTRUISM $get_token(DATA_PERSONALITY,1)
    	
    	if ( L_GREED < 99 )
    	{
    		add L_GREED PARAM1
    		subtract L_ALTRUISM PARAM1
    		capvar L_GREED 1 99	
    		capvar L_ALTRUISM 1 99
    
    		token.set DATA_PERSONALITY 0 L_GREED
    		token.set DATA_PERSONALITY 1 L_ALTRUISM
          quest set ent_me personality DATA_PERSONALITY
    	}	
    }
    is this now setting the questdata persistent on the character ?

    To the formatting issue, I am having a hard time to see what the fuck is wrong with it xD. Did you mean by wrong formatting that my { for the if statement was not put further in ? If thats so I think i fixed that, thats one of the problems if you are used to environments that do this stuff for you... it never got explained that its important topkek.

    PS ignore the ent_me for now I know I have to do it another way if its gonna end up as npc, since you are right that an npc is involved at some point.
     
  6. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    15,079
    54
    Apr 8, 2005
    psycho-oligist
    lost
    Well, the question was, how are you compiling it to realize it fails? Our compiler isn't publically available, and it doesn't fail to compile, regardless of what you throw at it, as it has no sanity check. Meanwhile the test_scripts system "compiles" at run time, so...

    But yeah, as you can probably tell from the various example scripts, else is not required.

    :roll: Yes, I suppose if you don't check it, you could end up pegging out the stat, and just decreasing the one you're subtracting from until it reaches 1 - though that could be as intended.

    You could, although wouldn't necessarily need to, if you read the quest data and wrote the local back to the quest data before you exited the event. It's probably cleaner to do it via a script-wide setvard anyways, but you would have to look out for that setvard being altered when multiple players accessed the same NPC.

    Not sure about putting this in the header though. If it's part of the player script, the header is going to load before the player spawns (ie. at the selection screen). Quest data won't be script side accessible at that point.

    Also:
    Code:
    {
    	if ( $get_token($get_quest_data(ent_me,personality),0) == 0 ) //gets the token from the quest personality should return 0 if not assgined
    	{   
    		quest set ent_me personality "50;50;50;50"
    	}
    }
    
    {   
    	setvard DATA_PERSONALITY $get_quest_data(ent_me,personality)
    }
    Would be more optimal as:
    Code:
    {
    	setvard DATA_PERSONALITY $get_quest_data(ent_me,personality)
    
    	if ( $get_token(DATA_PERSONALITY,0) == 0 ) 
    	{ 
    		setvard DATA_PERSONALITY "50;50;50;50"
    		quest set ent_me personality DATA_PERSONALITY 
    	}
    }
    No need to harass the player for quest data twice.

    Though, again, suspect you'd need this to be some place other than the header. If it was an NPC, you'd probably want it at the top of game_menu_getoptions, and ent_me would instead be PARAM1. (Keep in mind what happens if two players access the NPC at once though - may need some preventative measures to prevent cross-contamination.)

    Tabbing isn't important, save for my sanity, but the problem is you were opening brackets after a terminating conditional, and this would confuse the parser, as it isn't expecting them.

    In your original script, the parser would be running through it like so:
    Code:
    	if Greed < 99 //stop if not true
    	{ //new event?
    		add Greed PARAM1 //this is part of the header, or something, now
    Thus, chaos.

    If you're lucky, it'd generate an error in the log_msdll.log or the console, and if not, it would resolve in some strange way (such as being considered a new header event).

    In this case, you already changed the token data in at "token.set DATA_PERSONALITY 0 L_GREED" (etc), so all you need to do is write back the modified token string.

    quest set <target> personality DATA_PERSONALITY

    In another scenario, you'd build the token data and send it back. eg.
    Code:
    local L_VAR1 50
    local L_VAR2 25
    local L_VAR3 whatever
    local L_SOME_TOKENS '' //note this is two single 'quotes' making a null.
    token.add L_SOME_TOKENS L_VAR1 
    token.add L_SOME_TOKENS L_VAR2 
    token.add L_SOME_TOKENS L_VAR3 
    //L_SOME_TOKENS = "50;25;whatever"
    quest set QUEST_TARGET personality L_SOME_TOKENS
    But yes, "quest set <target> personality VAR_1;VAR_2..." won't work, and putting the vars in quotes will send back a literal string, rather than the vars.
     
  7. Phosphorcracker

    Phosphorcracker New Adventurer

    72
    0
    Nov 30, 2012
    looking for Occupation...
    Glorious Germany
    one more try : I never compiled anything in msc, i am however used from MSC unrelated compilers that missing else statments can lead to odd behaviour and felt more on the secure side adding them even doe they are empty.

    nvm

    Moving all the questdata calls and checks to the event makes it run a few lines more code but should prevent cross contamination if i got things right in my head. Also needs to be in every event since there is no way of foretelling what stat the player would get to change first...
     
  8. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    15,079
    54
    Apr 8, 2005
    psycho-oligist
    lost
    You could save yourself some future trouble, and stick the get quest data sequence in a single event, so you end up with something like this:
    Code:
    { gain_greed
    
    	local L_PLAYER_ID_EVENT PARAM1
    	callevent get_personality L_PLAYER_ID_EVENT //where we get/init the personality quest data
    	
    	local L_GREED $get_token(L_DATA_PERSONALITY,0)
    	local L_ALTRUISM $get_token(L_DATA_PERSONALITY,1)
    }
    And the future is now, as you messed this bit up:
    Code:
    	local L_DATA_PERSONALITY $get_quest_data(ent_me,personality)
    
       	if ( $get_token(DATA_PERSONALITY,0) == 0 ) 
       	{ 
     		setvard DATA_PERSONALITY "50;50;50;50"
       		quest set L_PLAYER_ID_EVENT personality L_DATA_PERSONALITY 
       	}
    ^ yer setting the quest data to the local that has the quest data you pulled, meaning, it will be forever 0... (Also it's still pulling from ent_me).

    You don't actually need the local L_DATA_PERSONALITY in any of these, just switch em up to all up to the setvard DATA_PERSONALITY, and I think it'd be fine.
     
  9. Phosphorcracker

    Phosphorcracker New Adventurer

    72
    0
    Nov 30, 2012
    looking for Occupation...
    Glorious Germany
    6am... tomorrow fo sure xD

    since tomorrow is today here we go again http://pastebin.com/cV2uzU5M i honestly have no clue how i oversaw that flaw
    i kinda noticed as the dialogue wouldnt stop giving stat at some point but was too flashed to actually think about it.

    So now once the stat reaches 99 the dialogue isnt giving a feedback anymore till i choose the counter part that lowers the stat so i can raise it again what tells me that it works this time fo sure.

    I have no clue what to do about it that multiple ppl talking to the npc might end up fudging stats. Isnt msc anyway build the way that only 1 player can interact with them ? like frosty only talks to one at time and stores break if a 2nd player tries to activate it...

    Oyster would like to have a way to check those stats ingame, i was thinking something similar to the command listresist that just puts them out in the combat box thingy ? how would i do that ?
     
  10. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    15,079
    54
    Apr 8, 2005
    psycho-oligist
    lost
    Well, it won't, cuz you have that <99 check. You *could* use an else statement to say, for instance, "You've dun maxed out greed, you wallstreet bastard."

    The way you've rigged this up, it won't be a problem. Even if, by some mind boggling coincidence, two players hit a menu option in the same frame, the server will still process them in order of index. There's no delay between the time they select a quest option and the time this is saved back to their quest data, since you're pulling and setting that all in the same frame based on their selection, rather than when they first activate the menu.

    Simplest to rig the NPC to generate a help tip when you click on him.

    Multi-line help tips are generated with file pipes, so something along the lines of:
    Code:
    { game_menu_getoptions
    
    	callevent get_personality $get(PARAM1,id)
    	local L_TIP_TITLE 'Current standing...'
    	local L_TIP_LINE 'Greed: '
    	stradd L_TIP_LINE $get_token(DATA_PERSONALITY,0)
    	stradd L_TIP_LINE |
    	stradd L_TIP_LINE 'Altruism: '
    	stradd L_TIP_LINE $get_token(DATA_PERSONALITY,1)
    	stradd L_TIP_LINE |
    	stradd L_TIP_LINE 'Piety: '
    	stradd L_TIP_LINE $get_token(DATA_PERSONALITY,2)
    	stradd L_TIP_LINE |
    	stradd L_TIP_LINE 'Pride: '
    	stradd L_TIP_LINE $get_token(DATA_PERSONALITY,3)
    	helptip PARAM1 generic L_TIP_TITLE L_TIP_LINE
    	[...]
    You could make this a separate event to more easily display it both before and after activating a menu option.

    One thing I didn't mention, is since you're doing math operations on these vars, they may pick up float placeholder, which may look a bit ugly. (In other words, greed 55, may return "55.00") Easiest way to avoid this is flattening it via $int() when you store the number, so...
    Code:
    token.set DATA_PERSONALITY 0 $int(L_GREED)
    Would fix that artifact, storing only the integer.
     
  11. greatguys1

    greatguys1 Active Adventurer Developer Warriors of the North

    279
    34
    Apr 20, 2013
    Yes
    Problem with a setvard on DATA_PERSONALITY though is if another person uses the menu, the original data will be overwritten, giving the first player the second player's data.
     
  12. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    15,079
    54
    Apr 8, 2005
    psycho-oligist
    lost
    That would be a problem (and was, when the idea was to pull the data on menu use, rather than at selection), but under his current script, the entire calculation, both pulling and setting the quest data for a single player, is handled in the same frame.

    Scripts aren't multi-threaded, only one sequence gets processed at a time. In this case, it isn't possible for another player to cause the variable holding the quest data to get overwritten before it finishes processing for the first.
     
  13. Phosphorcracker

    Phosphorcracker New Adventurer

    72
    0
    Nov 30, 2012
    looking for Occupation...
    Glorious Germany
    duh it does because the cap is 99 and 99 != < 99 so it does what i wanted it to do, absolutely nothing, allthough you are right that it would be better to get a message telling whats up, easy fix probably a good quality of life addition.

    http://puu.sh/rJKoZ/6060a30c03.jpg works like a charm, iam too lazy to find some funny phrases...

    also since i only add and subtract chances are they are not becoming a float. nvm they are becoming a float...

    welp this always displayed only the last stat pride... could be it would run too fast or the other 3 lines never got written ? also in scripting alldocs you made a comment that you never seen stradd work properly ?
    An event probably does the trick

    It just wont work... meh, i could print it to player console because i could use vars there but that would hide it too much imo. Unless there is a way to give playermessage a variable ?

    got it to kinda work http://puu.sh/rJMiK/93d87b887b.jpg with
    Code:
    { get_current_standing
    
    	local L_DATA_PERSONALITY_CS $get_quest_data(PARAM1,personality)
    	local L_TIP_TITLE 'Current Standing: '
    	local L_TIP_LINE 'Greed: '
    	stradd L_TIP_LINE $get_token(L_DATA_PERSONALITY_CS,0)
    	local L_TIP_LINE1 'Altruism: '
    	stradd L_TIP_LINE1 $get_token(L_DATA_PERSONALITY_CS,1)
    	local L_TIP_LINE2 'Piety: '
    	stradd L_TIP_LINE2 $get_token(L_DATA_PERSONALITY_CS,2)
    	local L_TIP_LINE3 'Pride: '
    	stradd L_TIP_LINE3 $get_token(L_DATA_PERSONALITY_CS,3)
    	helptip PARAM1 generic L_TIP_TITLE L_TIP_LINE L_TIP_LINE1 L_TIP_LINE2 L_TIP_LINE3
    }
    
    it wont for whatever reason keep any spacebar, might need to keep spaces with _

    wootwoot http://puu.sh/rJMyQ/3e7cd5f634.jpg
    Code:
    { get_current_standing
    
    	local L_DATA_PERSONALITY_CS $get_quest_data(PARAM1,personality)
    	local L_TIP_TITLE Current Standing: '
    	local L_TIP_LINE Greed: '
    	stradd L_TIP_LINE $get_token(L_DATA_PERSONALITY_CS,0)
    	local L_TIP_LINE1  |Altruism: '
    	stradd L_TIP_LINE1 $get_token(L_DATA_PERSONALITY_CS,1)
    	local L_TIP_LINE2  |Piety: '
    	stradd L_TIP_LINE2 $get_token(L_DATA_PERSONALITY_CS,2)
    	local L_TIP_LINE3  |Pride: '
    	stradd L_TIP_LINE3 $get_token(L_DATA_PERSONALITY_CS,3)
    	helptip PARAM1 generic L_TIP_TITLE L_TIP_LINE L_TIP_LINE1 L_TIP_LINE2 L_TIP_LINE3
    }
     

Share This Page