• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Is there a way to detect if player is in a region?

Status
Not open for further replies.

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,207
I want to detect when player's camera is inside a region, is there a way to do this? The camera is not locked in my map.
You will need to periodically poll the player's camera target if it is inside the point is inside the desired rect/region. Be aware that the player camera target is probably a local value (I cannot find a native that takes a player value) so the value of each player will have to be synchronized before use if the map is multiplayer otherwise players will go out of sync.
 
Level 13
Joined
May 10, 2009
Messages
868
I remember that I read a tutorial related to gamecache synchronizing data among players, and it might be quite useful for you:
[code=jass] - A really really ridiculously easy way to sync data / new GetHost command
Combining that with the following natives should do the job.
JASS:
constant native GetCameraTargetPositionX    takes nothing returns real
constant native GetCameraTargetPositionY    takes nothing returns real
native IsPointInRegion              takes region whichRegion, real x, real y returns boolean

Though it requires a considerable amount of time in order to sync your data, so you won't be able to update any camera position within a small interval.
 
Level 11
Joined
Jun 2, 2004
Messages
849
Triggering an event is "using" the information.

The other players do not have knowledge of where your camera is, so the trigger running on their computer will do something different, resulting in a desync.
 
Depends on what is done after; pseudo code:

Code:
if Cam_XY_IsAtRegion...() then

    // For some player this is true
    Action_A()

else

    // For some player this is not true
    Action_B()

endif

For some player Action_A() will run, for some player Action_B() will run. So if some actions don't or exclusivly run for only some players, which have global effect, then this is a sync problem.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,207
when player's camera is inside a point
The player's camera can never be inside a point as a point has no area or volume for the camera to be in.

You will need to periodically sync the camera locations of all players. Once the locations are synced you can test if they are inside a rect or region and run the appropriate actions. If you do not sync them then the actions will run only on the client who's camera is above the rect or region and so cause a desync as the actions will not happen for the other clients.
 
Level 13
Joined
May 10, 2009
Messages
868
I've come up with the following code, and I have tested it in a LAN with a virtual machine running windows 7. It didn't get desync'd. Also, I don't have friends who play warcraft 3 anymore, so I can't test it on BNet.

JASS:
function SyncPlayerCameraXYZ takes player whichPlayer returns nothing
    local string spid = I2S(GetPlayerId(whichPlayer))
    if GetLocalPlayer() == whichPlayer then
        // Locally store camera position
        call StoreReal(udg_GPCXY_Gamecache, spid, "X", GetCameraTargetPositionX())
        call StoreReal(udg_GPCXY_Gamecache, spid, "Y", GetCameraTargetPositionY())
        call StoreReal(udg_GPCXY_Gamecache, spid, "Z", GetCameraTargetPositionZ())
        // Order game cache to synchronize previous-stored coordinates
        call SyncStoredReal(udg_GPCXY_Gamecache, spid, "X")
        call SyncStoredReal(udg_GPCXY_Gamecache, spid, "Y")
        call SyncStoredReal(udg_GPCXY_Gamecache, spid, "Z")
    endif
    call TriggerSyncStart()
    call TriggerSyncReady()
endfunction

function SyncCameraXYZ takes nothing returns nothing
    local integer i = 0
    local string spid = ""
    local player locp = GetLocalPlayer()
    loop
        exitwhen i > 11
        if locp == Player(i) then
            set spid = I2S(GetPlayerId(Player(i)))
            // Locally store camera position
            call StoreReal(udg_GPCXY_Gamecache, spid, "X", GetCameraTargetPositionX())
            call StoreReal(udg_GPCXY_Gamecache, spid, "Y", GetCameraTargetPositionY())
            call StoreReal(udg_GPCXY_Gamecache, spid, "Z", GetCameraTargetPositionZ())
            // Order game cache to synchronize previous-stored coordinates
            call SyncStoredReal(udg_GPCXY_Gamecache, spid, "X")
            call SyncStoredReal(udg_GPCXY_Gamecache, spid, "Y")
            call SyncStoredReal(udg_GPCXY_Gamecache, spid, "Z")
        endif
        set i = i + 1
    endloop
    set locp = null
    call TriggerSyncStart()
    call TriggerSyncReady()
endfunction

function IsPlayerCameraInRect takes player whichPlayer, rect whichRect returns boolean
    local string spid = I2S(GetPlayerId(whichPlayer))
    local real x = GetStoredReal(udg_GPCXY_Gamecache, spid, "X")
    local real y = GetStoredReal(udg_GPCXY_Gamecache, spid, "Y")
    return x >= GetRectMinX(whichRect) and x <= GetRectMaxX(whichRect) and y >= GetRectMinY(whichRect) and y <= GetRectMaxY(whichRect)
endfunction

// Optional
function GetPlayerCameraX takes player whichPlayer returns real
    return GetStoredReal(udg_GPCXY_Gamecache, I2S(GetPlayerId(whichPlayer)), "X")
endfunction

function GetPlayerCameraY takes player whichPlayer returns real
    return GetStoredReal(udg_GPCXY_Gamecache, I2S(GetPlayerId(whichPlayer)), "Y")
endfunction

function GetPlayerCameraZ takes player whichPlayer returns real
    return GetStoredReal(udg_GPCXY_Gamecache, I2S(GetPlayerId(whichPlayer)), "Z")
endfunction

//===========================================================================
function InitTrig_GetPlayerCameraXY takes nothing returns nothing
    if udg_GPCXY_Gamecache == null then
        call FlushGameCache(InitGameCache("HIVEGPCXY"))
        set udg_GPCXY_Gamecache = InitGameCache("HIVEGPCXY")
    endif
endfunction

Simple demo
  • Demo All Players
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Cinematic - Clear the screen of text messages for (All players)
      • Custom script: call SyncCameraXYZ()
      • Set GPCXY_Rect = Rect00 <gen>
      • For each (Integer A) from 1 to 2, do (Actions)
        • Loop - Actions
          • Set GPCXY_Player = (Player((Integer A)))
          • Custom script: if IsPlayerCameraInRect(udg_GPCXY_Player, udg_GPCXY_Rect) then
          • -------- Either --------
          • Custom script: set udg_tmp_x = GetStoredReal(udg_GPCXY_Gamecache, I2S(GetPlayerId(udg_GPCXY_Player)), "X")
          • Custom script: set udg_tmp_y = GetStoredReal(udg_GPCXY_Gamecache, I2S(GetPlayerId(udg_GPCXY_Player)), "Y")
          • -------- Or --------
          • Custom script: set udg_tmp_x = GetPlayerCameraX(udg_GPCXY_Player)
          • Custom script: set udg_tmp_y = GetPlayerCameraY(udg_GPCXY_Player)
          • -------- However I would use the first one as you'd skip a function call --------
          • Set pnt = (Point(tmp_x, tmp_y))
          • Game - Display to (All players) for 6.00 seconds the text: ((Name of GPCXY_Player) + 's camera is within the rect.)
          • Special Effect - Create a special effect at pnt using Abilities\Spells\Orc\FeralSpirit\feralspiritdone.mdl
          • Special Effect - Destroy (Last created special effect)
          • Custom script: call RemoveLocation(udg_pnt)
          • Custom script: endif
  • Demo Specific Player
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
      • Player - Player 2 (Blue) skips a cinematic sequence
    • Conditions
    • Actions
      • Set GPCXY_Player = (Triggering player)
      • Set GPCXY_Rect = Rect00 <gen>
      • Custom script: call SyncPlayerCameraXYZ(udg_GPCXY_Player)
      • Custom script: if IsPlayerCameraInRect(udg_GPCXY_Player, udg_GPCXY_Rect) then
      • Game - Display to (All players) for 6.00 seconds the text: ((Name of GPCXY_Player) + 's camera is within the rect.)
      • Custom script: call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl", GetPlayerCameraX(udg_GPCXY_Player), GetPlayerCameraY(udg_GPCXY_Player)))
      • Custom script: endif
 

Attachments

  • SyncPlayerCamera.w3x
    19 KB · Views: 36
I've come up with the following code, and I have tested it in a LAN with a virtual machine running windows 7. It didn't get desync'd. Also, I don't have friends who play warcraft 3 anymore, so I can't test it on BNet.

Woah.. Even though I already found an easier way, you've put a lot of effort into scripting that. Kudos.

You should upload that system into spells section.
 
Level 13
Joined
May 10, 2009
Messages
868
Thanks, but I don't know if I should, because the snippet is a little bit simple, and the downside is that it's slow to get any camera position synchronized. Oh well, I believe the way you found is safer and better, but it was worth a shot though. :)
 
Here's how I did it:

  • Move Camera Unit
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Set LocalPlayer = (Picked player)
          • Custom script: if GetLocalPlayer() == udg_LocalPlayer then
          • Set CameraPoint[(Player number of (Picked player))] = (Target of current camera view)
          • Unit - Move CameraUnit[(Player number of (Picked player))] instantly to CameraPoint[(Player number of (Picked player))]
          • Custom script: endif
CameraUnit is a dummy unit for each player. He is periodically moved to the target location of the player's camera locally.

Will that cause a desync?
 
Level 13
Joined
May 10, 2009
Messages
868
I'm still skeptical about that one... I tried to reproduce it by removing collision, adding locust, both, but no success with it. Even if it doesn't desync, it would be a problem as soon as those units interact with anything, specially triggers.
 
Status
Not open for further replies.
Top