Jump to content


Photo

Scar script questions


16 replies to this topic

#1 BloodyVomit

BloodyVomit
  • Members
  • 9 posts

Posted 17 November 2019 - 02:03 AM

Can anyone help me with scar script? I have added a modal ability in game, but I have not found any examples of adding a hotkey to it. Is there any possibility to do it?
Actually, in my case any script for tracking keyboard button get pressed is suitable. No need to add a hotkey to the ability itself, but it will work as the hotkey.

#2 Kasrkin84

Kasrkin84

    title available

  • Members
  • 329 posts
  • Location:Birmingham, UK
  • Projects:Strongholds, Unification

Posted 17 November 2019 - 10:53 AM

AFAIK you can only use Scar to assign hotkeys to SGroups (i.e. squads) and EGroups (i.e. buildings), but not abilities.


Edited by Kasrkin84, 17 November 2019 - 05:36 PM.


#3 BloodyVomit

BloodyVomit
  • Members
  • 9 posts

Posted 18 November 2019 - 01:00 AM

I thought it is possible because autoexec.lua allows to bind some hotkeys to functions, but this code isn't presented in any other place. 
And as I said I do not need a hotkey. Any script to detect specialized key pressed will be enough. I only found Misc_DetectKeyboardInput() but it detects any input, not a specialized key input.


#4 EzArIk

EzArIk
  • Members
  • 7 posts
  • Projects:Legio~Cybernetica, [To.Be.Announced],....,etc.

Posted 21 November 2019 - 09:07 PM

(there is a map made by fuggles called Khorne’s driving school for the gifted, which allows the player to control their Rhino tank with the keyboard, I believe the SCAR file with that map details a good example of how to check for specific key presses)

Edited by EzArIk, 21 November 2019 - 09:07 PM.


#5 BloodyVomit

BloodyVomit
  • Members
  • 9 posts

Posted 24 November 2019 - 02:07 AM

(there is a map made by fuggles called Khorne’s driving school for the gifted, which allows the player to control their Rhino tank with the keyboard, I believe the SCAR file with that map details a good example of how to check for specific key presses)

 

Unfortunately this code is using 1-0 keys, but I need usual letter hotkeys.

 

But I have another question - is it possible to use repeat-until cycles in scar? I tried one, but game just stopped until I kill it process through windows task manager. Maybe I've done some mistakes or I should avoid this cycle? 

While and for cycles works, but for my code I suppose repeat-until will work better.



#6 Gambit

Gambit

    title available

  • Members
  • 6,718 posts
  • Location:Athens, Greece

Posted 24 November 2019 - 11:02 AM

Repeat->Until / While, are risky...

Especially if the exiting condition is "poorly" coded. I mean, what if it takes 10000 loops in order for the conditions to be met?

 

I always use a "for", and make (say) 20 attempts. And I put the condtitions within the loop, and if they are met, then I use a "break".


-In search of Papasmurf...

#7 Kasrkin84

Kasrkin84

    title available

  • Members
  • 329 posts
  • Location:Birmingham, UK
  • Projects:Strongholds, Unification

Posted 24 November 2019 - 11:12 AM

Repeat->Until / While, are risky...

Especially if the exiting condition is "poorly" coded. I mean, what if it takes 10000 loops in order for the conditions to be met?

 

I always use a "for", and make (say) 20 attempts. And I put the condtitions within the loop, and if they are met, then I use a "break".

 

Same here. You don't want your script to get caught in an infinite loop - I accidentally did this once, I'd rather not repeat it.



#8 BloodyVomit

BloodyVomit
  • Members
  • 9 posts

Posted 24 November 2019 - 12:33 PM

I can explain. I use cycles to create random unrepeatable talks every 30 seconds. The map is pretty short, so I want to use as more intel events as possible. But if random will choose same number 2 times in a row the script will skip whole code and no intel event for 60 seconds. So I want to use cycles to reroll random number of intel event.
While I was writing the comment I understood what mistake I had made and how to improve my code. Just need some conditions with breaks inside the repeat-until

#9 Gambit

Gambit

    title available

  • Members
  • 6,718 posts
  • Location:Athens, Greece

Posted 24 November 2019 - 05:45 PM

If I understood correctly, you can code it differently - no loop needed.

1] Put all the "talks" in an array.

2] Each time you need one, randomly chose one from the total array entries, play it, and DELETE that entry from the array.

3] Have a random (within logical time limits) re-calling of the same rule, to achieve that  :grad:  (Rule Add One Shot).

 

Even if you do not want to use step 3], consider using the Array idea, in order TO EXCLUDE playing the same "Talk".


-In search of Papasmurf...

#10 BloodyVomit

BloodyVomit
  • Members
  • 9 posts

Posted 25 November 2019 - 02:09 AM

I understand your idea and maybe it's better than mine. But still I post it, as it doesn't require rewriting the array of intel events\

'Rule_MissionStart is called from OnInit after starting NIS is played'
function Rule_MissionStart()
 if not Event_IsAnyRunning() then
  'Here I create 2 tables, first for intel events, second for check is it played or not'
  t_RandomIE ={EVENTS.IE_RandomNIS1, 'and so on, 10 talks in summ'}
  t_RandomIEPlayed = {false, false, false, false, false, false, false, false, false, false}
  'Activate the repeating random talks'
  Rule_AddInterval(Rule_RandomIE, 30)
 end
end
​
function Rule_RandomIE()
 'Check for no other events'
 if Event_IsAnyRunning() == false then
  'Start cycle at least one time'
  repeat
   'Change variable until we find one that was not played. g_random is a variable from OnGameSetup'
   g_random = World_GetRand(1, 10)
  until t_RandomIEPlayed[g_random] == false
  'Play the event from the top table with the number given from the cycle'
  Util_StartIntel(t_RandomIE[g_random])
  'Mark this event played'
  t_RandomIEPlayed[g_random] = true
  'This is a variable from OnGameSetup. It will stop this rule if all events are already played'
  g_random_ie_counter = g_random_ie_counter + 1
 end
 'There is actual stop. If we played 10 events we will stuck in infinite loop in repeat-until 
 So we need to stop the rule to prevent infinite loop
 The rule is stopped on the tenth time of being executed, so no need to create conditions in the start of the rule'
 if g_random_ie_counter == 10 then
  Rule_Remove(Rule_RandomIE)
 end
end

Edited by BloodyVomit, 25 November 2019 - 02:47 AM.


#11 Gambit

Gambit

    title available

  • Members
  • 6,718 posts
  • Location:Athens, Greece

Posted 25 November 2019 - 09:03 AM

Ahem....

No, this is not the "proper" way brother BloodyVomit. Although, it WILL work.

 

See, the repeat is still there, and yeah, it WILL exit eventually - but the number of loops is still random.

Just think that at the 10nth entry, there will be 9 "trues" and 1 "false" array entries, so the loop will run until that specific "false" is chosen. This is an unnecessary number of calculations.

 

If you were to:

1] remove the Repeat.

2] after each choice, instead of having the entry set to "true", just remove it from the table, and

3] choose based on this: g_random = World_GetRand(1, table.getn(t_RandomIEPlayed)) instead of this: g_random = World_GetRand(1, 10),

it would be much better!

 

And you need not use this exiting condition: if g_random_ie_counter == 10 then

But this: if table.getn(t_RandomIEPlayed) == 0 then

 

Bottomline, you do not even need to use a loop at all :p

Just delete each entry you play, and re-select from an array with "trimmed" entries, until they reach 0.

 

Just saying...


-In search of Papasmurf...

#12 BloodyVomit

BloodyVomit
  • Members
  • 9 posts

Posted 25 November 2019 - 11:22 AM

I understand, that my code is not good, that's why I ask for help. Just show it right from the SCAR to ensure you understand what I mean. Your variation is better, because it doesn't need second array and any cycles. Actually, I have never worked with Lua before, so I have taken the code from another campaigns SCARs and change it a little for my needs.



#13 fuggles

fuggles

    title available

  • Members
  • 4,849 posts

Posted 01 December 2019 - 11:33 AM

My smack talk mode may do what you need, albeit it doesn't add checks to ensure it's not played before, but easy enough to do. I'd give each event a number and then add a number to a table when played, when the rng rolls then check against the table.

#14 BloodyVomit

BloodyVomit
  • Members
  • 9 posts

Posted 13 December 2019 - 03:12 AM

Another day - another problem. Not really a problem, but a good question. I need to check how many of certain fully constructed buildings a player has. Unfortunately, relic didn't include a function for that, however they included two others functions: 

Player_GetBuildingsCountOnly - counts the number of buildings owned by player, however building can be not complited

Player_HasBuildingType - finds if this player owns any of the indicated building type and they are fully constructed, but it returns boolean, so only one building will trigger it

I have tryed to combine this two functions in one or even created a new one, but failed. Maybe someone of you have already resolved such problems or can help me with it?


Edited by BloodyVomit, 13 December 2019 - 03:19 AM.


#15 Gambit

Gambit

    title available

  • Members
  • 6,718 posts
  • Location:Athens, Greece

Posted 13 December 2019 - 10:48 AM

I do not know if there is one...

So I wrote one just now. It was a 5 minutes' job, and I have not tested it!!!

You may even find spelling errors in it :p

Here:

function Player_GetCompletedBuildingsCount(playerID)
    local count = 0
    local isDoneBuilding = function(egroupid, itemindex, entityID)
        if Entity_IsBuilding(entityID) and Entity_GetBuildingProgress(entityID) == 1.0 then
            count = count + 1
        end
    end
    EGroup_ForEach(Player_GetEntities(playerID), isDoneBuilding)
    return count
end

It should return an integer.

 

 

Sorry man but as I said, no time to test it.... Please do it yourself, and modify it.


-In search of Papasmurf...

#16 BloodyVomit

BloodyVomit
  • Members
  • 9 posts

Posted 13 December 2019 - 11:19 AM

Oh, internet issues prevent me to notify that I have already done it by slightly modifying Player_GetBlueprintCount function.

 

@Gambit, thanks man, but your code counts all complited buildings, but I needed specific, namely necron generators.

 

Here is my code (not actually my, 99% of it is relic code):

function Player_HasNumberOfBuildingsType( player, blueprintname )
	local CountBlueprints = function(groupCaller, groupID)
		local blueprintCount = 0
		local Counter = function(groupID, itemIndex, itemID)
			if (groupCaller.GetItemBlueprint(itemID) == blueprintname) then
				if Entity_IsBuilding(itemID) and Entity_GetBuildingProgress(itemID) >= 1.0 then
					blueprintCount = blueprintCount + 1
				end
			end
			return true
		end
		groupCaller.ForEachAllOrAny(groupID, true, Counter)
		return blueprintCount
	end
	if( EBP_Exists( blueprintname ) ) then
		-- count entity blueprints
		return CountBlueprints( EGroupCaller, Player_GetEntities( player ) )
	end
	error("Invalid blueprint name "..blueprintname )
end

Edited by BloodyVomit, 13 December 2019 - 11:21 AM.


#17 Gambit

Gambit

    title available

  • Members
  • 6,718 posts
  • Location:Athens, Greece

Posted 13 December 2019 - 01:41 PM

@Gambit, thanks man, but your code counts all complited buildings...

I was under the impression, this is what you were after...

 

But I guess all good now :thumbsuphappy:


Edited by Gambit, 13 December 2019 - 01:41 PM.

-In search of Papasmurf...



Reply to this topic



  


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users