STEAM GROUP
Left 4 Dead 2 Workshop Beta L4D2WSB
STEAM GROUP
Left 4 Dead 2 Workshop Beta L4D2WSB
4
IN-GAME
22
ONLINE
Founded
15 October, 2012
shotgunefx 12 Feb, 2013 @ 10:06am
Vscript Suggestions
Great update. Still diving in, but some quicks thoughts based on what people have asked for help on over the years and things I’ve wanted to do myself that I think would be helpful for mutations but also custom campaigns.

FYI These appear to be undocumented...
.IsSurvivor()
.GetActiveWeapon()
.GetZombieType()

Things that would be really useful to have

.IsPlayerIncapacitated()

Some way to distinguish between real Health, Real vs Temporary
GetRealHealth() // returns actual health regardless of temporary health. Also maybe SetRealHealth(num)

.IsDead() // would be nice though this could be derived from (player.GetHealth() == 1 && !player.IsPlayerIncapacitated())
.IsGhost()
.isHangingFromLedge()

CDirector::HowAngy () // returns a value between 0-1

CDirector.GetMaxSurvivorFlow() // returns the total flow to the saferoom/rescue instead of hard coding it per map like the bridge gauntlet

Something like nav_flow_target that doesn’t affect scoring so we can make survivors go to places off the flow or in a non-linear fashion. That or have the nav_flow_target’s original map spawn location used in scoring regardless of where it’s moved to when recomputing flow. Currently directing flow this way breaks scoring as the first target aquired they get 100% travel

Input to make a bot move to location of caller. Similar to nb_move_to_cursor

Input to make a bot attack caller.

Something like TraceLineTraceLine(Vector, Vector, handle) from Portal’s vscript. Right now it’s virtually impossible to interact with the world dynamically.

The ability to read entity KeyValues would also be nice
Last edited by shotgunefx; 28 Mar, 2013 @ 12:43pm
< >
Showing 1-15 of 19 comments
Kerry 12 Feb, 2013 @ 10:50am 
Thanks, those are great suggestions! We have a long list of features that would be nice to have, but we'll be using the beta feedback to prioritize so keep them coming.
shotgunefx 12 Feb, 2013 @ 11:32am 
Well, you asked for it ;)

Off the top of my head, I would have liked to have seen some Director hooks along the lines of EnvEntityMaker


OnSpawnSpecial(type, props)
OnSpawnCommon(props)

Both could modify the table of parameters. So you could transmute the type (like ConvertZombieClass) but also change any of the entity properties such as health, speed, model or skin. Returning null would cancel the spawn. I know some of this is do-able in the new mutation system but I don't know if it works in non-mutation modes.

I don't know if you can actually modify individual commons as I know they are somewhat of a collective entity but as an example


DirectorOptions -> {
function OnSpawnCommon(props){
// vary common speed and health
props[health] = props[health] + RandomInt(-10,10)
props[zspeed] = props[zspeed] + RandomInt(-10,10) // I just made up zspeed but I digress..
return props
}

function OnSpawnSpecial(etype, props){
TankMdls <- [
["models\infected\hulk.mdl", 0 ],
["models\infected\super_tank.mdl",2000]
];
if (etype == ZOMBLIE_TANK){
// spawn a tank or super tank
local tanktype = RandomInt(0,1);
props[health] = props[health]+ TankMdls[tanktype][1];
props[model] = props[health]+ TankMdls[tanktype][0];

}
return props
}

}



shotgunefx 12 Feb, 2013 @ 12:10pm 
One more though ... for generalizing mutations without having to spec them to a specific map, having some way of retrieving a spawn point in the flow would be nice.
vector GetSpawnPosition( int prefereddirection, float distance) // Retrieves a spawn position in given flow direction using furthest survivor in flow, or furthest behind depending on preferreddirection vector GetSpawnPositionFrom(vec frompos, int prefereddirection, float distance) // Retrieves a spawn position in given flow direction from vec

ex: spawn_at <- GetSpawnPosition(SPAWN_IN_FRONT_OF_SURVIVORS, 1000); // returns null if it fails

Maybe a way of ascertaining flow relative to survivors for any given entity as well, Something like...

int IsAheadInFlow(vec) // true if ahead, false otherwise

So for instance , say you wanted to randomly spawn things behind doors, you could loop through the prop_door_rotatings, collect the ones further in flow (IsAheadInFlow) then use GetSpawnPositionFron on the door to make sure you spawn behind it, Of course it would be helpful to know if the door was open, unlocked etc.


Also, the code from the previous post in code tags. I guess I should have read the formatting help. Too bad we can't preview posts

DirectorOptions -> { function OnSpawnCommon(props){ // vary common speed and health props[health] = props[health] + RandomInt(-10,10) props[zspeed] = props[zspeed] + RandomInt(-10,10) // I just made up zspeed but I digress.. return props } function OnSpawnSpecial(etype, props){ TankMdls <- [ ["models\infected\hulk.mdl", 0 ], ["models\infected\super_tank.mdl",2000] ]; if (etype == ZOMBLIE_TANK){ // spawn a tank or super tank local tanktype = RandomInt(0,1); props[health] = props[health]+ TankMdls[tanktype][1]; props[model] = props[health]+ TankMdls[tanktype][0]; } return props } }

bruhlord 12 Feb, 2013 @ 3:43pm 
Yeah, IsPlayerIncapped() would be fantastic. Great suggestions!
Rectus 13 Feb, 2013 @ 1:22am 
I'd like to stress on the usefullness of being able to read entity keyvalues. It would be an invaluable tool for passing data between maps and vscipts. Right now it doesn't seem possible to get dynamically generated values (ex. from a math_counter) to a vscript.

The other way around seems to have the methods __KeyValueFromInt(key,int), etc., but do those work with any arbitrary keyvalue?
shotgunefx 13 Feb, 2013 @ 1:55pm 
As far as I know Rectus they do. Whether they always get transmitted to client.. some of them aren't supposed to change.

On another note, can ConvertZombieClass() just always work?

I may be missing something, but trying to do something "somewhat" along the lines of Tankkk in coop and the only part I'm having a problem with is what I would think should be the simplest, spawning tanks.

Since ZSpawn doesn't raycast and we don't yet have something like GetSpawnPosition, I'm stumped. Since the spawns are totally dependent on gameplay even hardcoding them to a map really won't work well.

Also on my previous suggestion, IsAheadInFlow(vec), kind of silly would make much more sense to just have a function that returned the flow distance and using it's sign.
Fish 15 Feb, 2013 @ 9:11am 
Another handy feature would be a function that sets a player to "it". Making common infected target him/her. Much like boomer :)
Rectus 15 Feb, 2013 @ 9:31am 
Functions for Incapping/Unincapping and killing players would also be good.
Fish 15 Feb, 2013 @ 9:35am 
Definitely! The ability to uncap and kill players!!
shotgunefx 15 Feb, 2013 @ 9:36am 
Also IsDead()

As far as making a player IT, you can mimic that somewhat with CommandABot, commons may still choose other targets on their path. but I think that happens with being IT too. I'm assuming being IT has a lot of other side effects as far as spawing

BOT_CMD_ATTACK <- 0 function AttackTargetByName(name) { AttackTable <- { bot = null target = null cmd = BOT_CMD_ATTACK } local target = Entities.FindByName(null,name); if (target) { local z; while (z = Entities.FindByClassname(z,"infected")){ AttackTable.bot = z AttackTable.target = target CommandABot(AttackTable); } } } AttackTargetByName("!rochelle") // test
Fish 15 Feb, 2013 @ 9:38am 
Originally posted by shotgunefx:
Also IsDead()

As far as making a player IT, you can mimic that somewhat with CommandABot, commons may still choose other targets on their path. but I think that happens with being IT too. I'm assuming being IT has a lot of other side effects as far as spawing

BOT_CMD_ATTACK <- 0 function AttackTargetByName(name) { AttackTable <- { bot = null target = null cmd = BOT_CMD_ATTACK } local target = Entities.FindByName(null,name); if (target) { local z; while (z = Entities.FindByClassname(z,"infected")){ AttackTable.bot = z AttackTable.target = target CommandABot(AttackTable); } } } AttackTargetByName("!rochelle") // test

Damn, that CommandABot command is bloody powerful! :)
Fish 15 Feb, 2013 @ 4:34pm 
Another good one would be playerbot.SetFollowTarget( player instance ) and playerbot.GetFollowTarget() to make the playerbot act as the targets pet.
shotgunefx 16 Feb, 2013 @ 12:58pm 
A few other things that have come to mind

player.IsDead()

From Portal2
int CBaseEntity::entindex()

Maybe functions for SetParent SetParentAttachment, but you can work around those with DoEntFire

Also would be nice to be able to play non-game sounds on an entity.

Setting nexthink on an entity
I don't know if it's possible on an individual basis. 10fps for trying to manually animate something is very choppy. And many things don't need to think very often at all.

I know in Portal2 you can bump up the limit for all.

Last edited by shotgunefx; 16 Feb, 2013 @ 1:01pm
Fish 16 Feb, 2013 @ 7:46pm 
Player.SetAnimation() is another good one. For example, when they are pouring gas. It would be quite nice to set the default animation for doing a timed event.

What if you returned a true or false value for NextThink, to determine whether the bot continues with the default think process? :/
shotgunefx 16 Feb, 2013 @ 8:04pm 
From what I've seen (and the way I'm referring to it) nexthink is just the next time to think, so for something you were trying to animate you could set it to 33ms to get 30fps instead of 10fps.
< >
Showing 1-15 of 19 comments
Per page: 1530 50