Jump to content


Replying to Scar script questions


Post Options

    • Can't make it out? Click here to generate a new image

  or Cancel


Topic Summary

Gambit

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:


BloodyVomit

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

Gambit

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.


BloodyVomit

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?


fuggles

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.

BloodyVomit

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.


Gambit

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...


BloodyVomit

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

Gambit

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".


BloodyVomit

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

Review the complete topic (launches new window)