Page 1 of 1

Is it possible to control the spectate camera?

Posted: Mon Jun 18, 2018 4:49 pm
by Zeus
wondering if i'm able to manipulate the spectate camera, move it, have it look at an entity and set properties like FOV

im guessing that the spec camera is an entity i could find within the game and mess with it there?

Re: Is it possible to control the spectate camera?

Posted: Mon Jun 18, 2018 7:26 pm
by Kami
Hey,

I'm not sure if you mean a player beeing on spectator or if you mean the SourceTV specators.

In case you mean the spectating players that are on the server you can do things like this:

Syntax: Select all

from players.entity import Player
from events import Event
from players.helpers import inthandle_from_userid
import random
from filters.players import PlayerIter

rand_users = []

@Event('player_say')
def say(ev):
player = Player.from_userid(int(ev['userid']))
for play in PlayerIter('alive'):
rand_users.append(play.userid)
user_to_spec = random.choice(rand_users)
player.observer_mode = 4
player.observer_target = inthandle_from_userid(user_to_spec)

#To change the FOV
player.set_property_uchar('m_iDefaultFOV', 120)


This would set your specate view to a random player and also change your FOV (just an example for you)

There are three observer_modes I could find in CS:S:

Code: Select all

   #4 first person
   #5 third person
   #7 free roaming

Re: Is it possible to control the spectate camera?

Posted: Mon Jun 18, 2018 7:40 pm
by Zeus
I think what i'm looking to do is create my own version of the autodirector feature of sourcetv.

Something that those watching the game and shoutcasting can watch.

Re: Is it possible to control the spectate camera?

Posted: Tue Jun 19, 2018 8:13 pm
by quartata
As far as I can tell, controlling HLTV from a plugin is actually fairly straightforward. One of the interfaces you can get is IHLTVServer (core.get_interface("HLTVServer001", None)). From here, you can get IHLTVServer::BroadcastEvent (don't know the offset, on mobile) to control the camera. The simplest HLTV event is hltv_fixed (fixed camera shot), which you can construct like any other game event: it takes posx, posy, posz for the position of the camera, target for the index of the entity to look at and fov for the camera's FOV. I'll try to construct a full snippet when I get home.

Re: Is it possible to control the spectate camera?

Posted: Tue Jun 19, 2018 8:24 pm
by quartata
You can see all the HLTV game events the client listens for here (and how they're handled): https://github.com/ValveSoftware/source ... camera.cpp

Re: Is it possible to control the spectate camera?

Posted: Tue Jun 19, 2018 8:42 pm
by quartata
A better auto director would be a very interesting project. The auto director in TF2 at least is quite dumb. Aside from the stock HL2DM behavior (which is decent, but not for teamplay) it pretty much just adds fixed shots of the objective and chase camera shots when a building is destroyed https://github.com/NicknineTheEagle/TF2 ... rector.cpp

Re: Is it possible to control the spectate camera?

Posted: Thu Jun 21, 2018 11:16 pm
by quartata
Very very annoying... even though there's an INTERFACEVERSION_HLTVSERVER defined they actually never exposed it... I guess I'll have to scan for a function to get it.

Re: Is it possible to control the spectate camera?

Posted: Thu Jun 21, 2018 11:36 pm
by quartata
OK, so turns out the IHLTVDirector (which you can get the IHLTVServer from) is properly exposed. Unfortunately, this segfaults when trying to call IHLTVDirector::GetHLTVServer in load():

Syntax: Select all

import core
import commands.typed
import entities.entity
import events.custom
import events.variable
import mathlib
import memory
import paths

BROADCAST_EVENT_OFFSET = 23 if core.PLATFORM == "windows" else 24
GET_HLTV_SERVER_OFFSET = 4 if core.PLATFORM == "windows" else 5

SERVER_PATH = paths.GAME_PATH + "/bin/server_srv.so"
INTERFACEVERSION_HLTVDIRECTOR = "HLTVDirector001"

CAMERA_OFFSET = mathlib.Vector(0, 0, 200)

broadcast_event = None
hltv_server = None


class Hltv_Fixed(events.custom.CustomEvent):
posx = events.variable.LongVariable()
posy = events.variable.LongVariable()
posz = events.variable.LongVariable()

theta = events.variable.LongVariable()
phi = events.variable.LongVariable()

target = events.variable.ShortVariable()
fov = events.variable.FloatVariable()


def load():
global broadcast_event
global hltv_server

hltv_director = core.get_interface(SERVER_PATH, INTERFACEVERSION_HLTVDIRECTOR)
if not hltv_director:
raise Exception("can't get IHLTVDirector")

hltv_server = hltv_director.make_virtual_function(GET_HLTV_SERVER_OFFSET,
memory.Convention.THISCALL,
(memory.DataType.POINTER,),
memory.DataType.POINTER)(hltv_director)

broadcast_event = hltv_server.make_virtual_function(BROADCAST_EVENT_OFFSET,
memory.Convention.THISCALL,
(memory.DataType.POINTER, memory.DataType.POINTER),
memory.DataType.VOID)


@commands.typed.TypedServerCommand("stv_test")
def stv_test(_, ent_name):
target = entities.entity.BaseEntity.find(ent_name)

if not target:
core.echo_console("No such entity.")
return

camera_pos = target.origin + CAMERA_OFFSET
event = Hltv_Fixed(posx=camera_pos.x, posy=camera_pos.y, posz=camera_pos.z,
target=target.index, fov=90.0)

broadcast_event(hltv_server, memory.get_object_pointer(event))


Maybe someone better than me can see what I did wrong (it's entirely possible I have the offsets wrong, I had some trouble getting them)

Re: Is it possible to control the spectate camera?

Posted: Thu Jun 21, 2018 11:47 pm
by quartata
Also it looks memory.get_object_pointer doesn't work to get the underlying IGameEvent* like I had hoped either

Re: Is it possible to control the spectate camera?

Posted: Fri Jun 22, 2018 6:17 am
by Ayuto
get_object_pointer() doesn't work, because the CustomEvent class doesn't implement the _ptr() method.
Also, if that method is implemented, you don't need to get the pointer on your own. SP does that under the rug.

I will make some changes today, so you can get the underlying event.

Re: Is it possible to control the spectate camera?

Posted: Fri Jun 22, 2018 6:00 pm
by Ayuto
I have thought about my planned changes a little bit and decided to not add them. Use this to create the event:

Syntax: Select all

from events.manager import game_event_manager

def create_hltv_fixed_event(pos, target, fov, offset, theta, phi):
event = game_event_manager.create_event('hltv_fixed', True)
event.set_float('posx', pos.x)
event.set_float('posy', pos.y)
event.set_float('posz', pos.z)
event.set_short('theta', theta)
event.set_short('phi', phi)
event.set_short('target', target)
event.set_float('fov', fov)
event.set_short('offset', offset)
return event


To get the HLTV pointer, you can use something like this:
viewtopic.php?p=8103#p8103

Re: Is it possible to control the spectate camera?

Posted: Sat Jun 23, 2018 12:08 am
by quartata
Oh, I didn't know gameeventmanager was exposed directly. Otherwise that's what I would have done :P