Jump to content

[Solved] How to add new speech quotes?


Recommended Posts

Hello, if someone can help me that'd be great!

So, here's the code!

modmain.lua

Spoiler

local function Roar_Damage(v)
	if not v.components.health:IsDead() then
		if v:HasTag("sleeper") and v.components.sleeper and v.components.sleeper:IsAsleep() then v.components.sleeper:WakeUp() end
		if v:HasTag("spider") then v.components.locomotor:Sop() v.components.locomotor:Clear() end
		v.components.health:DoDelta(-10.4166666667)
		v.sg:GoToState("hit")
	end
end

local function Roar_Player_Damage(v)
	if not v.components.health:IsDead() and not v:HasTag("playerghost") and not v.prefab == "watan" then
		if v:HasTag("sleeper") and v.components.sleeper and v.components.sleeper:IsAsleep() then v.components.sleeper:WakeUp() end
		v.components.health:DoDelta(-2.08333333334)
		v.components.sanity:DoDelta(-2.08333333334)
		v.sg:GoToState("hit")
	end
end

local function Roar_Start(inst)
	if not inst.components.health:IsDead() then
		local x, y, z = inst.Transform:GetWorldPosition()
		
		local close_players = GLOBAL.FindPlayersInRange(x, y, z, (20), true)
		local closer_players = GLOBAL.FindPlayersInRange(x, y, z, (15), true)
		local very_far_players = GLOBAL.FindPlayersInRange(x, y, z, (60), true)
		local very_close_players = GLOBAL.FindPlayersInRange(x, y, z, (10), true)
		local super_close_players = GLOBAL.FindPlayersInRange(x, y, z, (5), true)
		
		local close_entities = GLOBAL.TheSim:FindEntities(x, y, z, 20, {"_health", "_combat"}, {"player", "veggie", "hive", "soundproof", "wall", "perfect", "shadow", "shadowminion", "shadowchesspiece"})
		local closer_entities = GLOBAL.TheSim:FindEntities(x, y, z, 15, {"_health", "_combat"}, {"player", "veggie", "hive", "soundproof", "wall", "perfect", "shadow", "shadowminion", "shadowchesspiece"})
		local very_close_entities = GLOBAL.TheSim:FindEntities(x, y, z, 10, {"_health", "_combat"}, {"player", "veggie", "hive", "soundproof", "wall", "perfect", "shadow", "shadowminion", "shadowchesspiece"})
		local super_close_entities = GLOBAL.TheSim:FindEntities(x, y, z, 5, {"_health", "_combat"}, {"player", "veggie", "hive", "soundproof", "wall", "perfect", "shadow", "shadowminion", "shadowchesspiece"})

		for _, v in pairs(close_entities) do
			if not v.components.health:Isead() and not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
				for i = 0.7, 1.8, 0.1 do
					v:DoTaskInTime(i, function(v)
						if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
							Roar_Damage(v)
							
							for _, v in pairs(closer_entities) do
								Roar_Damage(v)
							end
							for _, v in pairs(very_close_entities) do
								Roar_Damage(v)
							end
							for _, v in pairs(super_close_entities) do
								Roar_Damage(v)
							end
							
						end
					end)
				end
			end
		end
		
		for _, v in pairs(close_players) do
			if inst.components.health and not inst.compnents.health:IsDead() and inst.sg:HasStateTag("roaring") then
				for i = 0.7, 1.8, 0.1 do
					v:DoTaskInTime(i, function(v)
						if v.components.health and not v.components.health:IsDead() and inst.components.health and not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
							Roar_Player_Damage(v)
							
							for _, v in pairs(closer_players) do
								Roar_Player_Damage(v)
							end
							for _, v in pairs(super-close_players) do
								Roar_Player_Damage(v)
							end
							
						end
					end)
				end
			end
		end
		
	end
end

 

so this is code for my character can do a roar to damage stuff around him, the roar damages entities entities fine but not players. So, I don't want the roar to affect my character obviously so in the "Roar_Player_Damage" I put a check not not damage if the prefab is my character prefab "watan" but then the code doesn't affect any players!

If I remove that then it will damage my player once & cancel the roar, I have no idea what I'm doing wrong.. if someone can help me with this then that would really be nice, thanks for your time & have a good day/night :D!!

Edited by SuperDavid
Link to comment
Share on other sites

Did you debug it? I mean putting some "print" statements in your code, eg. just print "v.prefab" to see what it is?

Why did you make the for loops this way? I mean why does the close_players loop looks different to the others and why are the others within the first loop? That does not looks right and I'm sure it is causing problems.
What do you want to achieve this way?

Edited by Serpens
Link to comment
Share on other sites

3 hours ago, Serpens said:

Did you debug it? I mean putting some "print" statements in your code, eg. just print "v.prefab" to see what it is?

I don't know how I would do that unfortunately.

 

3 hours ago, Serpens said:

Why did you make the for loops this way? I mean why does the close_players loop looks different to the others and why are the others within the first loop? That does not looks right and I'm sure it is causing problems.
What do you want to achieve this way?

Well basically this is what I want to do, when my char does a roar I want entities that are in 20 range to get hit from it, & for every 5 range closer to my char they take more damage!

This is why inside the "close_entities" there's more codes to do bonus damage to entities that are closer, that's the only way I knew how to do it since I'm not smart at coding.

Link to comment
Share on other sites

just put print(v.prevab) at begining of the Roar_damage_Player function and the prefab will be in the logfile. To better find it you can add more print statements, I usually do sth like:
print("HERE")
print(v.prefab)

Of course you can also do print("HERE: "..GLOBAL.tostring(v.prefab))  (GLOBAL only if you are in modmain), but first one is easier to write :D
 

How about simply giving different damage value, depening on how near they are?
eg. you could do:

local function Roar_Player_Damage(v,damage)
	if not v.components.health:IsDead() and not v:HasTag("playerghost") and not v.prefab == "watan" then
		if v:HasTag("sleeper") and v.components.sleeper and v.components.sleeper:IsAsleep() then v.components.sleeper:WakeUp() end
		v.components.health:DoDelta(-damage)
		v.sg:GoToState("hit")
	end
end
for _, v in pairs(closer_players) do
    Roar_Player_Damage(v,10)
end

and make the damage for very close player 15 or whatever value you want.
There is no need to call this function more than once per player.

But you could do it even better:
How about:
 

local function Roar_Start(inst)
    if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then -- it is better to check roaring here, so in case it is false, we do not have to find entities
        local x, y, z = inst.Transform:GetWorldPosition()
        
        local near_players = GLOBAL.FindPlayersInRange(x, y, z, (60), true)
        local near_entities = GLOBAL.TheSim:FindEntities(x, y, z, 20, {"_health", "_combat"}, {"player", "veggie", "hive", "soundproof", "wall", "perfect", "shadow", "shadowminion", "shadowchesspiece"})
        local distance = nil -- initialize it before we enter the loop
        
        for _, v in pairs(near_entities) do
            if not v.components.health:IsDead() and not inst.components.health:IsDead() then
                distance = math.sqrt(inst:GetDistanceSqToInst(v)) -- GetDistanceSqToInst is distance^2
                v:DoTaskInTime(distance/10, function(v)
                    Roar_Damage(v,20-distance) -- here no check if inst is dead, cause he already did the roar ~ up to 2 seconds ago, so even if inst is dying withing those 2 seconds, it still should hit the ent?
                end)
            end
        end
        
        for _, v in pairs(near_players) do
            if inst.components.health and not inst.components.health:IsDead() and v.soundproof == nil and not v:HasTag("playerghost") and v.components.health and not v.components.health:IsDead() then
                distance = math.sqrt(inst:GetDistanceSqToInst(v)) -- GetDistanceSqToInst is distance^2
                v:DoTaskInTime(distance/10, function(v)
                    Roar_Player_Damage(v,60-distance)
                end)
            end
        end
    end
end

and use the Roar_Player_Damage function from above and also add damage to your Roar_Damage function.

I used the distance directly now. So if distance is 10, the roar will take distance/10 = 1 second to reach that player and deals 60-distance=50 damage.  Of course you can adjust those values, but I think it is nice to use the distance here :)

What should happen if your character makes the roar but shortly after it is dying or stops roaring? I mean players far away are hit x seconds later. Should it still hit them, since the roar was already made? Or should it only possible to hit players more far away, if you roar at least x seconds without stop?
Depending on your answer you have to add to those above code the IsDead and HasTag("roaring") also in the DoTaskInTime function.

In the "for _, v in pairs(near_players) do" part you can of course also check if "inst==v" (or ~=) to not hit yourself.
Do you only want to not hit yourself, or do you not want to hit any player that is playing your character? In second case you can make the v.prefab check also here... or if you want in Roar_Player_Damage, does not matter I think.

Edited by Serpens
Link to comment
Share on other sites

On 9/25/2017 at 1:46 PM, Serpens said:

just put print(v.prevab) at begining of the Roar_damage_Player function and the prefab will be in the logfile. To better find it you can add more print statements, I usually do sth like:
print("HERE")
print(v.prefab)

Hey, so I put " print(v.prevab) " at beginning of Roar_damage_Player function & all I get in log & console is "nil", I don't really know what that's supposed to mean xD.. So I still have problem that players take no damage if I want my prefab to be unaffected.

On 9/25/2017 at 1:46 PM, Serpens said:

and make the damage for very close player 15 or whatever value you want.
There is no need to call this function more than once per player.

If I call function to check for players in closer range does it cause more lag or performance problem?

On 9/25/2017 at 1:46 PM, Serpens said:

In the "for _, v in pairs(near_players) do" part you can of course also check if "inst==v" (or ~=) to not hit yourself.
Do you only want to not hit yourself, or do you not want to hit any player that is playing your character?

I would like for roar to not affect anyone who is playing as my character, not just the player doing the roar :).

 

Thjanks for all your help so much man :wilson_laugh:!!

Edited by SuperDavid
Link to comment
Share on other sites

3 hours ago, SuperDavid said:

Hey, so I put " print(v.prevab) " at beginning of Roar_damage_Player function & all I get in log & console is "nil", I don't really know what that's supposed to mean xD.. So I still have problem that players take no damage if I want my prefab to be unaffected.

then now you know why it not works.
Now we have to find out why v.prefab is nil... I do not see any obvious reason...
Try print(v) and see what it prints in logs.
I think prefab should be known at server and at client, so this should not be the problem...

Link to comment
Share on other sites

When I put print(v) in that Roar_damage_Player  function in console it says my character's prefab name "watan" & any other player prefab that's in vicinity which I don't really know what that means either :lol:.. also thanks for your help :D!

Edited by SuperDavid
Link to comment
Share on other sites

So I guess my code counts my character as "v" not just other characters in range then it says that the code shouldn't happen if "v" is my prefab so it ends up doing nothing? I'm so confused about how to fix this, if anyone got some ideas that really be swell :D!

Link to comment
Share on other sites

5 hours ago, Serpens said:

Make sth like "why is preefab nil" ? Cause that is the only problem with your code, as far I can see.
And that is what you have to find out.

I don't understand what my prefab being "nil" means so I don't know what I have to find out to fix or what's wrong in with the code in the first place :(

Link to comment
Share on other sites

So right now you check to see what players are in the area including yourself.

After you perform that you need to exclude your character from being a potential target. Like Serpens mentioned you can use inst==v or you can check by tag if your character has a unique one.

for _, v in pairs(near_players) do
            if inst.components.health and not inst.components.health:IsDead() and v.soundproof == nil and not v:HasTag("playerghost") and v.components.health and not v.components.health:IsDead() and not inst==v then ...

 

and not inst==v or if you have a unique tag and not inst:HasTag("your character unique tag")

Edited by RedHairedHero
Link to comment
Share on other sites

@RedHairedHero Do you have a clue why inst.prefab=="xyz" is not working (inst.prefab is nil .. (in this case v.prefab)) ? From what I know it should work.

But yes, without solving this question, the best solution would be the tag, to also exclude other players playing your character.

@SuperDavid "nil" means "unknown" or "does not exist" (or more precisly "nothing"). So if prefab does not exist, it is not possible to do anything with it.

Edited by Serpens
Link to comment
Share on other sites

4 minutes ago, Serpens said:

@RedHairedHero Do you have a clue why inst.prefab=="xyz" is not working (inst.prefab is nil .. (or v.prefab)) ? From what I know it should work.

But yes, without solving this question, the best solution would be the tag, to also explude other players playing your character.

v is the prefab name in range. He mentioned it here when he performed the print.

On 9/26/2017 at 2:54 PM, SuperDavid said:

When I put print(v) in that Roar_damage_Player  function in console it says my character's prefab name "watan" & any other player prefab that's in vicinity which I don't really know what that means either :lol:.. also thanks for your help :D!

So doing v.prefab is essentially prefab.prefab which will mean nothing and always turn out to be nil. If you're needing to check by character name you can do if v == "watan"

Link to comment
Share on other sites

10 minutes ago, RedHairedHero said:

v is the prefab name in range. He mentioned it here when he performed the print.

So doing v.prefab is essentially prefab.prefab which will mean nothing and always turn out to be nil. If you're needing to check by character name you can do if v == "watan"

but looking at his code, it does not make such sense that v is the prefab ...
And if you print an instance of an player, you will get sth like "ID prefab" in the logfile. And I thought maybe he also got this, but only wrote that it is the prefab.

BUT while I looked at the code again, I noticed he is using "v" twice.
@SuperDavid You should rename the "_ , v" from close_players and close_entities to something different.
Your structure (loop in a loop) is not advisable, but since you want to use it, you have to be careful. And in the clse_players loop you are using this "v". But as soon you start the first loop in your loop. you are overwriting the v with etnities from closer_players.
So just rename those two to something different.
That does not solve the prefab question, but other bugs.

When you print(v) , is it really only the prefab in logfile? Or also an ID ? If it is the prefab, all of your code should not work, since you can not make prefab:HasTag(...)

 

edit: Try the renaming of v I suggested above. It could be that is also solves everything else. Not sure.

Edited by Serpens
Link to comment
Share on other sites

41 minutes ago, Serpens said:

But yes, without solving this question, the best solution would be the tag, to also exclude other players playing your character.

So, I used a tag & my character now doesn't get hurt which is great! It's weird checking its prefab didn't work though.

Anyways I have one more question, so I don't like using tags because it crashes the game if they exceed over 32, so I was wondering would it be fine to put

" inst.watan == true " inside my character's common_postinit or master_postinit & check for that instead of a tag? I put that in my common_postinit & it looks like it does same thing as tag would do :)?

Link to comment
Share on other sites

3 minutes ago, SuperDavid said:

So, I used a tag & my character now doesn't get hurt which is great! It's weird checking its prefab didn't work though.

Anyways I have one more question, so I don't like using tags because it crashes the game if they exceed over 32, so I was wondering would it be fine to put

" inst.watan == true " inside my character's common_postinit or master_postinit & check for that instead of a tag? I put that in my common_postinit & it looks like it does same thing as tag would do :)?

Do not forget to add the v fix posted above. This is really important, if more than one player is near.

To your question: I'm not 100% sure... The main problem about this solution is usually that it is 1) not saved and 2) not available for client. Therefore you usually do not do it that way.   But if you put it in those postinits, it is executed at every gamestart and I think it is also called for clients. So if it works also with caves/for clients, I think in this case it should be fine.

Link to comment
Share on other sites

7 minutes ago, Serpens said:

But if you put it in those postinits, it is executed at every gamestart and I think it is also called for clients. So if it works also with caves/for clients, I think in this case it should be fine.

Well it works for both world with caves & no caves so I think it works fine :D!

8 minutes ago, Serpens said:

Do not forget to add the v fix posted above. This is really important, if more than one player is near.

I tested my function by spawning in more of my character prefab & did my roar & it didn't affect them or my character but it would affect other things like Wilson. So why is this important :)?

Link to comment
Share on other sites

One problem I would bring up would be that if you're performing these for loop checks by distance, who ever is close to you will be hit like 4 to 5 times, since they'll be within range for all of your checks. If it's intentional then nevermind.

Edited by RedHairedHero
Link to comment
Share on other sites

50 minutes ago, SuperDavid said:

Well it works for both world with caves & no caves so I think it works fine :D!

I tested my function by spawning in more of my character prefab & did my roar & it didn't affect them or my character but it would affect other things like Wilson. So why is this important :)?

just because you did not have the specific testcase yet, it does not mean that the bug can not happen ;)
Looking closer at your code I think because of using "DoTaskInTime" and not using the v after the loops it works "by accident" (btw is there any english word saying that something only works accidently/by luck/random ?? I think by accident is not the right wording?)

But it is important that you see the follwing (the more you understand, the less questions you have to ask in the forum):
Lets say "close_players" only contains your watan.
And closer_players contains wilson.

for _,v in pairs(close_players) do
    print(v) -- -> watan
    for _,v in pairs(closer_players) do
        print(v) -- -> wilson
    end
    print(v) -- not watan anymore, but wilson, cause you overwrote the v .
end

So it might be better, if you make a loop in a loop, to choose different naming.

Link to comment
Share on other sites

8 minutes ago, Serpens said:

(btw is there any english word saying that something only works accidently/by luck/random ?? I think by accident is not the right wording?)

I think you can say it happened by chance :).

 

So if I change code from this

Spoiler

for _, v in pairs(close_players) do
			if inst.components.health and not inst.components.health:IsDead() then
				for i = 0.7, 1.8, 0.1 do
					v:DoTaskInTime(i, function(v)
						if v.soundproof == nil and not v:HasTag("playerghost") and v.components.health and not v.components.health:IsDead() and inst.components.health and not inst.components.health:IsDead() and v.watan == nil then
							Roar_Player_Damage(v)
						end
					end)
				end
			end
		end

 

to this it would be better?

Spoiler

for _, close_players in pairs(close_players) do
			if inst.components.health and not inst.components.health:IsDead() then
				for i = 0.7, 1.8, 0.1 do
					close_players:DoTaskInTime(i, function(close_players)
						if close_players.soundproof == nil and not close_players:HasTag("playerghost") and close_players.components.health and not close_players.components.health:IsDead() and inst.components.health and not inst.components.health:IsDead() and close_players.watan == nil then
							Roar_Player_Damage(close_players)
						end
					end)
				end
			end
		end

 

so I basically replace "v" with "close_players"? Sorry if that's not what you're trying to say I'm kind of confused :lol:.

Link to comment
Share on other sites

@SuperDavid No :D not close_players, this would be fatal, since you are using same name for two different things :D

I mean instead of my example above, you can make:

for _,v in pairs(close_players) do
    print(v) -- -> watan
    for ~,t in pairs(closer_players) do
        print(t) -- -> wilson
    end
    print(v) -- now still watan, cause "t" is wilson now.
end

Changing the "_" to "~" is not that important, since you do not use it anywhere in your code. So it does not matter if you overwrite it or not.

Instead of using v or t variable names, you can of course also make:
for _ , close_player in pairs(close_players) do
(notice the difference player vs players. Just do not use the same naming twice.
Of course you can also use "for _,inst in pairs()" or any name you want, as long as you do no use it twice for different things in the same function.

Link to comment
Share on other sites

19 minutes ago, SuperDavid said:

I think you can say it happened by chance :).

 

So if I change code from this

  Reveal hidden contents


for _, v in pairs(close_players) do
			if inst.components.health and not inst.components.health:IsDead() then
				for i = 0.7, 1.8, 0.1 do
					v:DoTaskInTime(i, function(v)
						if v.soundproof == nil and not v:HasTag("playerghost") and v.components.health and not v.components.health:IsDead() and inst.components.health and not inst.components.health:IsDead() and v.watan == nil then
							Roar_Player_Damage(v)
						end
					end)
				end
			end
		end

 

to this it would be better?

  Reveal hidden contents


for _, close_players in pairs(close_players) do
			if inst.components.health and not inst.components.health:IsDead() then
				for i = 0.7, 1.8, 0.1 do
					close_players:DoTaskInTime(i, function(close_players)
						if close_players.soundproof == nil and not close_players:HasTag("playerghost") and close_players.components.health and not close_players.components.health:IsDead() and inst.components.health and not inst.components.health:IsDead() and close_players.watan == nil then
							Roar_Player_Damage(close_players)
						end
					end)
				end
			end
		end

 

so I basically replace "v" with "close_players"? Sorry if that's not what you're trying to say I'm kind of confused :lol:.

So here's an example of what your function is currently doing.

Let's say there's Tom, Jerry, Barry, and Larry.

Tom is close, Jerry is closer, Barry is very close, and Larry is super close.

The roar goes off.

The function checks what players are close. Tom, Jerry, Barry, and Larry are detected and take damage.

Then the closer loop goes. Jerry, Barry, and Larry are detected and take damage.

Then the very close loop goes. Barry and Larry are detected and take damage.

Then the super close loop goes. Larry is detected and takes damage.

Link to comment
Share on other sites

@Serpens Okay, I think I understand now :D!

So, if I put multiple "for ?, ? in pairs()" I should make the question marks be different letters if they're not affecting the same entities :)?

Is my code now good :)?

Spoiler

local function Roar_Damage(v)	--deal 504 damage to entities
	if not v.components.health:IsDead() then
		if v:HasTag("sleeper") and v.components.sleeper and v.components.sleeper:IsAsleep() then v.components.sleeper:WakeUp() end
		if v:HasTag("spider") then v.components.locomotor:Stop() v.components.locomotor:Clear() end
		v.components.health:DoDelta(-41.75)
		v.sg:GoToState("hit")
	end
end

local function Roar_Player_Damage(p)	--deal 96 health & 96 sanity damage to players
	if not p.components.health:IsDead() and not p:HasTag("playerghost") and p.watan == nil and p.soundproof == nil then
		if p:HasTag("sleeper") and p.components.sleeper and p.components.sleeper:IsAsleep() then p.components.sleeper:WakeUp() end
		p.components.health:DoDelta(-8.3)
		p.components.sanity:DoDelta(-8.3)
		p.sg:GoToState("hit")
	end
end

local function Roar_Start(inst)
	if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
		local x, y, z = inst.Transform:GetWorldPosition()
		
		local players = GLOBAL.FindPlayersInRange(x, y, z, (12), true)
		
		local far_players = GLOBAL.FindPlayersInRange(x, y, z, (60), true)
		
		local entities = GLOBAL.TheSim:FindEntities(x, y, z, 12, {"_health", "_combat"}, {"player", "veggie", "hive", "soundproof", "wall", "perfect", "shadow", "shadowminion", "shadowchesspiece"})
		
		
		if inst.components.health and not inst.components.health:IsDead() then
			for i = 0.7, 1.8, 0.1 do -- Start at i = 0.7 and go to 1.8 in 0.1 steps, repeats 12 times.
			
				inst:DoTaskInTime(i, function(inst)
					if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
						local fx = SpawnPrefab("groundpoundring_fx")
						if fx ~= nil then
							fx.Transform:SetPosition(x, y, z)
						end
					end
				end)
				
				for a, p in pairs(players) do
					p:DoTaskInTime(i, function(p)
						if p.soundproof == nil and not p:HasTag("playerghost") and p.components.health and not p.components.health:IsDead() and inst.components.health and not inst.components.health:IsDead() and p.watan == nil then
							Roar_Player_Damage(p)
						end
					end)
				end
					
				for _, v in pairs(entities) do
					v:DoTaskInTime(i, function(v)
						if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
							Roar_Damage(v)
						end
					end)
				end
					
			end
		end
		

for a, p in pairs(far_players) do
			p:DoTaskInTime(.7, function(p)
				inst.components.talker:Say(GetString(inst, "ANNOUNCE_WATANROAR"))
			end)
		end
		
	end
end

 

 

So, I have one more thing if you guys know how I can do it that would be great too :D!!

So, my roar has range of 12 distance, but I want players from up to range 60 distance to say something like a warning.

Which I have code like this in my function

Spoiler

for a, p in pairs(far_players) do
			p:DoTaskInTime(.7, function(p)
				inst.components.talker:Say(GetString(inst, "ANNOUNCE_WATANROAR"))
			end)
		end

 

the only problem is players in distance of being hit by the roar also say this quotes while being hit by the roar which is not what I want since it's supposed to be a warning xD. Do you know a way I can make this code not affect "players" & it only affects players outside of the "players" range?

Edited by SuperDavid
Link to comment
Share on other sites

1 hour ago, SuperDavid said:

@Serpens Okay, I think I understand now :D!

So, if I put multiple "for ?, ? in pairs()" I should make the question marks be different letters if they're not affecting the same entities :)?

Is my code now good :)?

  Reveal hidden contents


local function Roar_Damage(v)	--deal 504 damage to entities
	if not v.components.health:IsDead() then
		if v:HasTag("sleeper") and v.components.sleeper and v.components.sleeper:IsAsleep() then v.components.sleeper:WakeUp() end
		if v:HasTag("spider") then v.components.locomotor:Stop() v.components.locomotor:Clear() end
		v.components.health:DoDelta(-41.75)
		v.sg:GoToState("hit")
	end
end

local function Roar_Player_Damage(p)	--deal 96 health & 96 sanity damage to players
	if not p.components.health:IsDead() and not p:HasTag("playerghost") and p.watan == nil and p.soundproof == nil then
		if p:HasTag("sleeper") and p.components.sleeper and p.components.sleeper:IsAsleep() then p.components.sleeper:WakeUp() end
		p.components.health:DoDelta(-8.3)
		p.components.sanity:DoDelta(-8.3)
		p.sg:GoToState("hit")
	end
end

local function Roar_Start(inst)
	if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
		local x, y, z = inst.Transform:GetWorldPosition()
		
		local players = GLOBAL.FindPlayersInRange(x, y, z, (12), true)
		
		local far_players = GLOBAL.FindPlayersInRange(x, y, z, (60), true)
		
		local entities = GLOBAL.TheSim:FindEntities(x, y, z, 12, {"_health", "_combat"}, {"player", "veggie", "hive", "soundproof", "wall", "perfect", "shadow", "shadowminion", "shadowchesspiece"})
		
		
		if inst.components.health and not inst.components.health:IsDead() then
			for i = 0.7, 1.8, 0.1 do -- Start at i = 0.7 and go to 1.8 in 0.1 steps, repeats 12 times.
			
				inst:DoTaskInTime(i, function(inst)
					if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
						local fx = SpawnPrefab("groundpoundring_fx")
						if fx ~= nil then
							fx.Transform:SetPosition(x, y, z)
						end
					end
				end)
				
				for a, p in pairs(players) do
					p:DoTaskInTime(i, function(p)
						if p.soundproof == nil and not p:HasTag("playerghost") and p.components.health and not p.components.health:IsDead() and inst.components.health and not inst.components.health:IsDead() and p.watan == nil then
							Roar_Player_Damage(p)
						end
					end)
				end
					
				for _, v in pairs(entities) do
					v:DoTaskInTime(i, function(v)
						if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
							Roar_Damage(v)
						end
					end)
				end
					
			end
		end
		

for a, p in pairs(far_players) do
			p:DoTaskInTime(.7, function(p)
				inst.components.talker:Say(GetString(inst, "ANNOUNCE_WATANROAR"))
			end)
		end
		
	end
end

 

 

So, I have one more thing if you guys know how I can do it that would be great too :D!!

So, my roar has range of 12 distance, but I want players from up to range 60 distance to say something like a warning.

Which I have code like this in my function

  Reveal hidden contents


for a, p in pairs(far_players) do
			p:DoTaskInTime(.7, function(p)
				inst.components.talker:Say(GetString(inst, "ANNOUNCE_WATANROAR"))
			end)
		end

 

the only problem is players in distance of being hit by the roar also say this quotes while being hit by the roar which is not what I want since it's supposed to be a warning xD. Do you know a way I can make this code not affect "players" & it only affects players outside of the "players" range?

This is a stab in the dark, but should work.

local play = Point(inst.Transform:GetWorldPosition()) --This will provide the x,y,z coordinates for the main player

local rando = Point(p.Transform:GetWorldPosition()) This will provide the x,y,z coordinates for the random player

Once you have their coordinates you can perform a check to see if they're out past a certain distance. Here's a quick example.

local x = play.x - rando.x

local z = play.z - rando.z


if x <= 60 and x > 20 
  or x < -20 and x >= -60 
  or z =< 60 and z > 20 
  or z < -20 and z >= -60 then

--Have the character make their warning announcement.

end

 

So this will detect anyone who is past 20 and less then 60 away.

Link to comment
Share on other sites

@RedHairedHero

 I have this code right now

Spoiler

local function Roar_Start(inst)
	if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
		local x, y, z = inst.Transform:GetWorldPosition()
		
		local players = GLOBAL.FindPlayersInRange(x, y, z, (12), true)
		
		local far_players = GLOBAL.FindPlayersInRange(x, y, z, (60), true)
		
		local entities = GLOBAL.TheSim:FindEntities(x, y, z, 12, {"_health", "_combat"}, {"player", "veggie", "hive", "soundproof", "wall", "perfect", "shadow", "shadowminion", "shadowchesspiece"})
		
		
		if inst.components.health and not inst.components.health:IsDead() then
			for i = 0.7, 1.8, 0.1 do -- Start at i = 0.7 and go to 1.8 in 0.1 steps, repeats 12 times.
			
				inst:DoTaskInTime(i, function(inst)
					if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
						local fx = SpawnPrefab("groundpoundring_fx")
						if fx ~= nil then
							fx.Transform:SetPosition(x, y, z)
						end
					end
				end)
				
				for a, p in pairs(players) do
					p:DoTaskInTime(i, function(p)
						if p.soundproof == nil and not p:HasTag("playerghost") and p.components.health and not p.components.health:IsDead() and inst.components.health and not inst.components.health:IsDead() and p.watan == nil then
							Roar_Player_Damage(p)
						end
					end)
					
					local _other = Point(p.Transform:GetWorldPosition())
					local _inst = Point(inst.Transform:GetWorldPosition())
					
					local x = _inst.x - _other.x
					local z = _inst.z - _other.z

					if x <= 60 and x > 12 
					or x < -12 and x >= -60 
					or z <= 60 and z > 12 
					or z < -12 and z >= -60 then
					print("test1")
						p:DoTaskInTime(.7, function(p)
						print("test2")
							p.components.talker:Say(GetString(inst, "ANNOUNCE_DEERCLOPS"))
						end)
					end
				end
					
				for _, v in pairs(entities) do
					v:DoTaskInTime(i, function(v)
						if not inst.components.health:IsDead() and inst.sg:HasStateTag("roaring") then
							Roar_Damage(v)
						end
					end)
				end
					
			end
		end
		
		
	end
end

 

and the prints I put in the code don't ever go off, & the code never works no matter how far or close I am. Did I do something wrong(I probably did xD) :)?

And thanks for your help :D!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...