Draw box around bomb zone

Please post any questions about developing your plugin here. Please use the search function before posting!
User avatar
Kami
Global Moderator
Posts: 263
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Draw box around bomb zone

Postby Kami » Sat Mar 17, 2018 4:11 pm

Hey guys, I'm currently trying to draw a box around the bomb zones.

This is the code I use:

Syntax: Select all

from events import Event
from players.entity import Player
from filters.entities import EntityIter
from effects import beam
from filters.recipients import RecipientFilter
from mathlib import Vector
from engines.precache import Model
from effects import box

model = Model('sprites/tp_beam001.vmt')

@Event('player_say')
def say(ev):
cnt = 0
userid = int(ev['userid'])
player = Player.from_userid(userid)
for ent in EntityIter():
if ent.classname == 'func_bomb_target':
st = Vector(*ent.mins)
end = Vector(*ent.maxs)
st[2] += 50
end[2] = st[2]
do_box(st,end)



def do_box(start,end):
box(
RecipientFilter(),
start,
end,
alpha=255,
blue=255,
green=0,
red=255,
amplitude=0,
end_width=15,
life_time=7,
start_width=15,
fade_length=0,
flags=0,
frame_rate=255,
halo=model,
model=model,
start_frame=0
)


This works almost perfectly, but I have one problem. While one box is drawn perfectly the other one looks like this:

Image

When I add 300 to the height it shows correctly and someone told me that it might be because the lines start inside the worldspawn.

Any ideas how to fix this?

Edit: On de_dust2 the box does only draw on A (with all lines) and not a single line on B
decompile
Senior Member
Posts: 416
Joined: Sat Oct 10, 2015 10:37 am
Location: Germany
Contact:

Re: Draw box around bomb zone

Postby decompile » Sat Mar 17, 2018 10:18 pm

Some time ago I had problems with drawing many beams at once. I did it the exact same way as you, but I noticed that the game has a kind of limit of how many beams can be shown in one tick. (I suppose?)

The trick for me was, to draw them on the next tick with Delay(0, do_box, (st,end)).

Not sure if it helps here, but it could be a try worth.
User avatar
Kami
Global Moderator
Posts: 263
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Re: Draw box around bomb zone

Postby Kami » Sat Mar 17, 2018 11:33 pm

Thank you for your reply but sadly that was not the cause of the problem
User avatar
Ayuto
Project Leader
Posts: 2195
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Re: Draw box around bomb zone

Postby Ayuto » Mon Mar 19, 2018 7:14 pm

Beams are only rendered if the client sees the origins (if they are part of the PVS). I haven't yet figured out how to add an origin to the client's PVS (not sure if that is even possible). However, if you set the life time of a beam to 0, it's shown permanently. This seems to skip the PVS check on the client side, so all beams are drawn.

Edit:
If permanent beams are no solution for you, there might be a workaround. You can write your own box-function using CTEBeamEntPoint. This beam effect allows you to connect two entities using their indexes instead of locations:
https://github.com/Source-Python-Dev-Te ... nt.ini#L18

So, you simply create four invisible entities at the corners. Then, you can you can utilize these two flags when connecting the entities:
https://github.com/ValveSoftware/source ... .h#L29-L30

If haven't tested it but it's worth a try.
User avatar
Kami
Global Moderator
Posts: 263
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Re: Draw box around bomb zone

Postby Kami » Tue Mar 20, 2018 7:58 pm

I tried what you said and the result seems to be the same. I'm not sure I've done everything right though

Syntax: Select all

from events import Event
from players.entity import Player
from filters.entities import EntityIter
from effects import beam
from filters.recipients import RecipientFilter
from mathlib import Vector
from engines.precache import Model
from effects import box
from effects.base import TempEntity
from entities.entity import Entity
from entities.constants import MoveType

model = Model('sprites/tp_beam001.vmt')
ent_model = Model('models/props_c17/oildrum001.mdl')
ent_list = {}

@Event('player_say')
def say(ev):
cnt = 0
userid = int(ev['userid'])
player = Player.from_userid(userid)
for ent in EntityIter():
if ent.classname == 'func_bomb_target':
cnt += 1
st = Vector(*ent.mins)
end = Vector(*ent.maxs)
st[2] += 20
end[2] = st[2]
create_corners(st,end,cnt)
do_box()


def do_box():
points = [(ent_list[0],ent_list[1]),(ent_list[1],ent_list[3]),(ent_list[3],ent_list[2]),(ent_list[2],ent_list[0]),(ent_list[5],ent_list[6]),(ent_list[6],ent_list[8]),(ent_list[8],ent_list[7]),(ent_list[7],ent_list[5])]

for x,y in points:
entity = TempEntity('BeamEntPoint', start_entity_index=x,end_entity_index=y, model_index=model.index,halo_index=model.index,frame_rate=10, life_time=5.0, start_width=10, end_width=10, red=255, green=255, blue=255,alpha=255, speed=10)
entity.flags=1 << 11 | 1 << 12
entity.create()



def create_corners(start,end,number):
x1, y1, z1 = start
x2, y2, z2 = end
a = start
b = Vector(x2, y1, z1)
e = Vector(x1, y2, z1)
f = Vector(x2, y2, z1)

points = (a,b,e,f)
for counter,point in enumerate(points):
entity = Entity.create('prop_physics')
entity.origin = point
entity.model = ent_model
entity.spawn()
entity.move_type = MoveType.NONE
if number == 1:
ent_list[counter] = entity.index
else:
ent_list[counter+5] = entity.index


Edit: Using env_beam seems to have made it better, but still does not work completely as intended (for example on de_cbbl where there is the bomb spot between two big boxes, it does not draw a single line). This is the code I use right now:

Syntax: Select all

from events import Event
from players.entity import Player
from filters.entities import EntityIter
from effects import beam
from filters.recipients import RecipientFilter
from mathlib import Vector
from engines.precache import Model
from effects import box
from effects.base import TempEntity
from entities.entity import Entity
from entities.constants import MoveType
from entities.constants import SolidFlags
from colors import Color
from listeners import OnLevelInit

model = Model('sprites/tp_beam001.vmt')
ent_model = Model('models/props_c17/oildrum001.mdl')
ent_list = {}
beam_list = {}



@Event('player_say')
def say(ev):
userid = int(ev['userid'])
player = Player.from_userid(userid)
do_box()
for index in beam_list:
x,y = beam_list[index]
print("beam1: "+str(x)+" beam2: "+str(y))


def do_box():
points = [(ent_list[0],ent_list[1]),(ent_list[1],ent_list[3]),(ent_list[3],ent_list[2]),(ent_list[2],ent_list[0]),(ent_list[5],ent_list[6]),(ent_list[6],ent_list[8]),(ent_list[8],ent_list[7]),(ent_list[7],ent_list[5])]

for x,y in points:
index = points.index((x,y))
beam_one = create_beam(x,y)
beam_two = create_beam(x,y)
beam_list[index] = (beam_one,beam_two)





def create_beam(start,end):
start_entity = Entity(start)
end_entity = Entity(end)
beam = Entity.create("env_beam")
beam.spawn_flags = 1
beam.teleport(start_entity.origin, None, None)

beam.set_key_value_int('damage', 0)
beam.set_key_value_float('HDRColorScale', 1.0)
beam.set_key_value_int('life', 0)
beam.set_key_value_string(
'LightningStart', str(start))
beam.set_key_value_string(
'LightningEnd', str(end))
beam.set_key_value_int('Radius', 255)
beam.set_key_value_int('renderamt', 100)
beam.set_key_value_color('rendercolor', Color(255,255,255,255))
beam.set_key_value_int('StrikeTime', 1)
beam.set_key_value_string('texture', "sprites/laserbeam.spr")
beam.set_key_value_int('TextureScroll', 1)
beam.set_key_value_int('TouchType', 3)

beam.model = model
beam.set_property_vector('m_vecEndPos', end_entity.origin)

beam.spawn()
beam.flags=1 << 11 | 1 << 12

beam.call_input('TurnOff')
beam.call_input('TurnOn')
beam.call_input('Width',15.0)
return beam.index



def create_corners(start,end,number):
x1, y1, z1 = start
x2, y2, z2 = end
a = start #rechts oben
b = Vector(x2, y1, z1) #links oben
e = Vector(x1, y2, z1) #rechts unten
f = Vector(x2, y2, z1) #links unten
#A | E rechts oben
#B | F links oben
#C | G rechts unten
#D | H links unten

#0 - 1
#1 - 3
#3 - 2
#2 - 0

points = (a,b,e,f)
for counter,point in enumerate(points):
entity = Entity.create('prop_physics')
entity.origin = point
entity.model = ent_model
entity.spawn()
entity.move_type = MoveType.NONE
entity.target_name = ""+str(entity.index)
entity.solid_flags |= SolidFlags.NOT_SOLID
#entity.color = Color(255,255,255,0)
if number == 1:
ent_list[counter] = entity.index
else:
ent_list[counter+5] = entity.index

@Event('round_start')
def round_start(ev):
cnt = 0
for ent in EntityIter():
if ent.classname == 'func_bomb_target':
cnt += 1
st = Vector(*ent.mins)
end = Vector(*ent.maxs)
st[2] += 40
end[2] = st[2]
create_corners(st,end,cnt)
User avatar
Ayuto
Project Leader
Posts: 2195
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Re: Draw box around bomb zone

Postby Ayuto » Fri Mar 23, 2018 11:27 pm

Just a small hint: if you ever need an entity just to mark a position, better use info_target. Then you can use this function to "convert" a location to an entity:

Syntax: Select all

def create_target(origin):
entity = Entity.create('info_target')
entity.origin = origin
entity.spawn()
return entity
For me this works perfectly fine:

Syntax: Select all

from random import randint

from events import Event
from filters.entities import EntityIter
from engines.precache import Model
from entities.entity import Entity
from colors import BLUE
from colors import Color
from mathlib import Vector
from commands.say import SayCommand

model = Model('sprites/tp_beam001.vmt')

def load():
mark_bomb_zones()

@Event('round_start')
def on_round_start(event):
# TODO: Only need to do this once per map.
# env_beam persists during the whole map.
mark_bomb_zones()

@SayCommand('toggle')
def on_toggle(command, index, team_only):
for beam in EntityIter('env_beam'):
beam.call_input('Toggle')

@SayCommand('color')
def on_color(command, index, team_only):
for beam in EntityIter('env_beam'):
beam.color = Color(
randint(0, 255),
randint(0, 255),
randint(0, 255))

def mark_bomb_zones():
for zone in EntityIter('func_bomb_target'):
mark_zone(zone.mins, zone.maxs)

def mark_zone(start, end):
x1, y1, z1 = start
x2, y2, z2 = end

a = start
b = Vector(x2, y1, z1)
c = Vector(x2, y1, z2)
d = Vector(x1, y1, z2)
e = Vector(x1, y2, z1)
f = Vector(x2, y2, z1)
h = Vector(x1, y2, z2)
g = end

lines = (
# First square
(a, b),
(b, c),
(c, d),
(d, a),

# Second square
(e, f),
(f, g),
(g, h),
(h, e),

# Connection between both squares
(a, e),
(b, f),
(c, g),
(d, h)
)

for p1, p2 in lines:
create_beam(p1, p2)

def create_beam(p1, p2):
beam = Entity.create('env_beam')
beam.spawn_flags = 1
beam.model = model
beam.origin = p1
beam.color = BLUE

beam.set_key_value_int('damage', 0)
beam.set_key_value_int('life', 0)
beam.set_property_vector('m_vecEndPos', p2)

beam.spawn()
beam.call_input('Width', 15)
beam.call_input('TurnOn')

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 25 guests