|
|
#1 |
![]() Join Date: Feb 2012
Reputation: 0
Posts: 12
|
Create Entitys in Vscript?
The only way I've figured out how to create an entity in vscript is to use SendToConsole via ent_create. This method isn't ideal as the console commands don't wait for the script. Timing becomes a major issue as a result. I could use timers to delay but that's far from ideal as well and in some cases wont work.
This is what I'm currently using: Code:
SendToConsole("ent_create weapon_scavenge_item_spawn")
|
|
|
|
|
|
#2 |
![]() Join Date: Jan 2010
Reputation: 151
Posts: 2,407
|
Not in L4D2 solely with scripts, Portal 2 I believe can. They have a lot more functionality with vscripts.
SendToConsole is also going to respect cheat flags. It may help if you can give us more an idea of what you're trying to accomplish. env_entity_maker's have additional scripting support, so that's how you would normally create entities with script, but seeing you're not just adding these to the map, I'm guessing it's a mutation type of deal? |
|
|
|
|
|
#3 |
![]() Join Date: Feb 2012
Reputation: 0
Posts: 12
|
I guess you could call it a mutation... but not in the official capacity.
I am modifying a scavenge map (Mall Atrium) on the xbox 360. I'd like to add an additional generator for players to be able to fill gas cans. I'd also like to remove all the gas cans placed on the map by Valve then create new ones and place them in new locations. I have (most of) this already working by putting a vscript in scripts/vscripts. L4D2 will run a MapScript as long as the nut file is named the same as the map (c1m4_atrium.nut) Because this is all targeted at xbox gameplay I am unable to use hammer to do anything. Therefore I am having to do everything via console commands and vscript... I don't think there is any other way to do it. So I have been painfully piecing the below vscript together and testing by trial and error. The syntax is my biggest unknown. If anyone knows of a better way of doing what I am attempting I am all ears ![]() Code:
// Timer Flags
thirtiethsOfASecondTimer <- 0
entCreationDelayInThirtieths <- 3
entCreationTimerStartTime <- 0
// PreStage Flags
preStage <- 1
preStageTwoFirstTimeFlag <- 1
preStageThreeStartTime <- 0
// Phase Flags
phase <- 0
phaseOne <- 0
phaseTwoNumCansCreated <- 0
posX <- 0.0
posY <- 0.0
posZ <- 0.0
angX <- 0.0
angY <- 0.0
angZ <- 0.0
// New Scavenge Cans Orgin and Angles
scavCansPlacement <-
[
[ -3965, -4248.14, 547.719, 0, 314, 0 ],
[ -3930, -4248.14, 547.719, 0, 314, 0 ],
[ -2969.12, -4211.3, 291.719, 0, 0, 0 ],
[ -2930.27, -4249.96, 291.719, 0, 206, 0 ],
[ -2966, -4430.71, 292.219, 0, 30, 0 ],
[ -3835.71, -4434.21, 455.719, 0, 299, 0 ],
[ -3819.37, -4437.12, 455.719, 0, 57, 0 ],
[ -3807.98, -4430.94, 455.719, 0, 169, 0 ],
[ -4949.15, -4247.01, 291.719, 0, 310, 0 ],
[ -5776.49, -3071.39, 291.719, 0, 179, 0 ],
[ -5778.05, -3235.49, 291.719, 0, 33, 0 ],
[ -5779.84, -3221.33, 291.719, 0, 53, 0 ],
[ -3509.42, -3544.65, 291.719, 0, 219, 0 ],
[ -4072.38, -4471.76, 291.719, 0, 161, 0 ],
[ -4061.4, -4473.13, 291.719, 0, 164, 0 ],
[ -4051.47, -4474.47, 291.719, 0, 298, 0 ],
[ -3965, -4248.14, 547.719, 0, 314, 0 ],
]
function Update()
{
thirtiethsOfASecondTimer++
if(Director.GetGameMode() == "scavenge")
{
if(preStage == 1)
{
// THIS PHASE RUNS IMMEDIATELY!! THIS MEANS NOW! VERY FAST. AND PRETTY MUCH NOTHING WILL WORK HERE. SO DON'T TRY.
// YOU CAN SEND A MESSAGE TO THE CONSOLE TO TELL THAT THE SCRIPT IS RUNNING, BUT THAT'S ABOUT IT.
Msg("DOING PRESTAGE 1: INITIATING CUSTOM SCRIPT" + "\n")
preStage = 2
}
if(preStage == 2)
{
// THIS PHASE RUNS OVER AND OVER AND OVER UNTIL A COMMON ZOMBIE NECK MODEL CAN BE CREATED
if(preStageTwoFirstTimeFlag == 1)
{
Msg("DOING PRESTAGE 2: WAITING TILL CAN CREATE A ZOMBIE NECK MODEL" + "\n")
preStageTwoFirstTimeFlag <- 0
}
SendToConsole("sv_cheats 1")
SendToConsole("sb_all_bot_game 1")
SendToConsole("prop_dynamic_create infected/common_fem_infected_w_neck.mdl")
placeholderEnt <- null
while((placeholderEnt <- Entities.FindByModel(placeholderEnt,"models/infected/common_fem_infected_w_neck.mdl")) != null)
{
preStage = 3
preStageThreeStartTime <- thirtiethsOfASecondTimer + 15
}
}
if(preStage == 3)
{
if(thirtiethsOfASecondTimer >= preStageThreeStartTime)
{
// THIS PHASE WAITS FOR A BIT TO GIVE THE MODELS A CHANCE TO SPAWN (THEY LOAD SLOW OR SOMETHING)
Msg("DOING PRESTAGE 3: CREATING ZOMBIE NECK MODELS" + "\n")
placeholderEntTwo <- null
while((placeholderEntTwo <- Entities.FindByModel(placeholderEntTwo,"models/infected/common_fem_infected_w_neck.mdl")) != null)
{
placeholderEntTwo.__KeyValueFromString("targetname", "ZombieNecks")
}
preStage = 5
phaseOne = 1
phase <- 1
}
}
if(phaseOne == 1)
{
// YOU CAN DO PRETTY MUCH ANYTHING HERE
if(phase == 1)
{
Msg("DOING PHASE 1: REMOVE ZOMBIE NECK MODELS AND DOING CUSTOMIZATIONS" + "\n")
// DO THIS FIRST
SendToConsole("ent_remove_all ZombieNecks")
SendToConsole("ent_remove_all weapon_scavenge_item_spawn")
SendToConsole("prop_dynamic_create props_vehicles/radio_generator.mdl")
gasIndex <- 0
while(gasIndex < scavCansPlacement.len())
{
SendToConsole("ent_create weapon_scavenge_item_spawn")
gasIndex++
}
SendToConsole("ent_create point_prop_use_target")
Msg("\nStarting Timer\n")
entCreationTimerStartTime <- thirtiethsOfASecondTimer
phase++
}
if(phase == 2)
{
Msg("DOING YOUR PHASE 2: SPAWN AND POSITION GENERATOR MODEL, POINT_PROP_USE_TARGET & GAS CANS" + "\n")
if(thirtiethsOfASecondTimer - entCreationTimerStartTime == entCreationDelayInThirtieths)
{
Msg("\nNaming and moving generator\n")
gennyEnt <- Entities.FindByModel(null, "models/props_vehicles/radio_generator.mdl")
if(gennyEnt)
{
gennyEnt.__KeyValueFromString("targetname", "genny")
gennyEnt.SetOrigin(Vector(-4453.427246,-3974.960205,136.031250))
gennyEnt.SetForwardVector(Vector(0.0,84.455269,0.000000))
}
else
{
Msg("CANT FIND GENNY MODEL")
}
Msg("\nDone Naming and moving generator\n")
Msg("\nNaming and moving point_prop_use_target\n")
phil <- null
while((phil <- Entities.FindByClassname(phil, "point_prop_use_target")) != null)
{
if(phil)
{
philName <- phil.GetName()
if(philName.len() == 0)
{
phil.__KeyValueFromString("targetname", "phil")
phil.__KeyValueFromInt("spawnflags", 2)
phil.SetOrigin(Vector(-4399.12, -3971.36, 192.61))
phil.SetForwardVector(Vector(0 0 0))
}
}
}
Msg("\nDone Naming and moving point_prop_use_target\n")
Msg("\nNaming and moving Gas Cans\n")
ScvCan <- null
while((ScvCan <- Entities.FindByClassname(ScvCan, "weapon_scavenge_item_spawn")) != null)
{
if(ScvCan)
{
ScvCanName <- ScvCan.GetName()
if(ScvCanName.len() == 0)
{
ScvCan.__KeyValueFromString("targetname", "ScvCan")
ScvCan.__KeyValueFromInt("spawnflags", 2)
posX <- scavCansPlacement[phaseTwoNumCansCreated][0]
posY <- scavCansPlacement[phaseTwoNumCansCreated][1]
posZ <- scavCansPlacement[phaseTwoNumCansCreated][2]
angX <- scavCansPlacement[phaseTwoNumCansCreated][3]
angY <- scavCansPlacement[phaseTwoNumCansCreated][4]
angZ <- scavCansPlacement[phaseTwoNumCansCreated][5]
ScvCan.SetOrigin(Vector(posX, posY, posZ))
ScvCan.SetForwardVector(Vector(angX, angY, angZ))
phaseTwoNumCansCreated++
}
}
else
{
Msg("CANT FIND SCVCAN")
}
}
Msg("\nDone Naming and moving Gas Cans\n")
phase++
}
}
}
}
}
|
|
|
|
|
|
#4 | |
![]() Join Date: Jan 2010
Reputation: 151
Posts: 2,407
|
Quote:
Well here's a suggestion. Instead of trying to create new spawns and remove the old ones, just move them to the new locations using ent.SetOrigin(), it takes a vector, not numbers so you'd want it like can.SetOrigin(Vector(11,22,33)) You could store those Vector declarations in your array instead of numbers I think for the angles, can.SetForwardVector would do it Can you override the commentary txt file or no? If so, you could add entities to that |
|
|
|
|
|
|
#5 |
![]() Join Date: Jan 2010
Reputation: 151
Posts: 2,407
|
And as far as editing the commentary file...
If there's not already a Entity section, it looks like this Code:
"Entities"
{
entity
{
"id" "48530"
"classname" "point_viewcontrol"
"acceleration" "500"
"angles" "0 0 0"
"deceleration" "500"
"fov" "40"
"fov_rate" "1.0"
"spawnflags" "136"
"target" "!bill"
"targetattachment" "eyes"
"targetname" "poster_cam"
"wait" "10"
"origin" "6899 2077 55"
"vscripts" "lbcam.nut"
"thinkfunction" "Think"
"mapupdate" "1"
}
}
|
|
|
|
|
|
#6 |
![]() Join Date: Feb 2012
Reputation: 0
Posts: 12
|
There doesn't seem to be a commentary.txt file for c1m4_atrium.
There are commentary.txt files for other maps such as c1m2_streets_commentary.txt so I guess I'll just create one for c1m4_atrium_commentary.txt and see what happens... |
|
|
|
|
|
#7 |
![]() Join Date: Jan 2010
Reputation: 151
Posts: 2,407
|
If you can do that, you should have a lot more flexibility
|
|
|
|
|
|
#8 |
![]() Join Date: Feb 2012
Reputation: 0
Posts: 12
|
So I was able to use the commentary file to create a few gas cans on the map! Nice! But... can you elaborate more about what entities don't work in the commentary file? The reason I ask is because I am unable to get a simple static_prop into the map using the commentary file.
This is what I have (the gas cans spawn but the static_prop kitchen table does not) Code:
"Entities"
{
"entity"
{
"classname" "weapon_scavenge_item_spawn"
"angles" "90 -120 0"
"body" "0"
"disableshadows" "1"
"glowstate" "3"
"model" "models/props_junk/gascan001a.mdl"
"skin" "0"
"solid" "0"
"spawnflags" "2"
"targetname" "scavcan"
connections
{
"OnItemPickedUp" "@director:runscriptcode:DirectorScript.MapScript.LocalScript.GasCanTouched():0:-1"
}
"origin" "-4648.000 -3712.000 62.031"
editor
{
"color" "0 0 200"
"visgroupid" "2"
"visgroupshown" "1"
"visgroupautoshown" "1"
"logicalpos" "[5000 4000]"
}
"mapupdate" "1"
}
"entity"
{
"classname" "weapon_scavenge_item_spawn"
"angles" "90 -120 0"
"body" "0"
"disableshadows" "1"
"glowstate" "3"
"model" "models/props_junk/gascan001a.mdl"
"skin" "0"
"solid" "0"
"spawnflags" "2"
"targetname" "scavcan"
connections
{
"OnItemPickedUp" "@director:runscriptcode:DirectorScript.MapScript.LocalScript.GasCanTouched():0:-1"
}
"origin" "-4648.000 -3712.000 62.031"
editor
{
"color" "0 0 200"
"visgroupid" "2"
"visgroupshown" "1"
"visgroupautoshown" "1"
"logicalpos" "[5000 4000]"
}
"mapupdate" "1"
}
"entity"
{
"classname" "prop_static"
"angles" "0 0 0"
"disableselfshadowing" "1"
"disablevertexlighting" "1"
"fademindist" "-1"
"fadescale" "1"
"model" "models/props_interiors/table_kitchen.mdl"
"renderamt" "255"
"rendercolor" "255 255 255"
"skin" "0"
"solid" "6"
"origin" "-3987.69 -3665.84 1"
editor
{
"color" "255 255 0"
"visgroupshown" "1"
"visgroupautoshown" "1"
"logicalpos" "[0 1500]"
}
"mapupdate" "1"
}
}
Thanks again. |
|
|
|
|
|
#9 | |
![]() Join Date: Jan 2010
Reputation: 151
Posts: 2,407
|
Quote:
prop_dynamic I believe works, though I don't know if that will work with that particular model. If not probably could use a prop_dynamic_override or something. As far as what doesn't work, I've only tried a few things. I don't think brush triggers work, but I can't remember a 100%, prop_physics don't seem to wake up on their own on map load. You could probably specify it's location exactly and then just wake it up via script. Other than that, you'll probably have to just figure it out by trial and error |
|
|
|
|
|
|
#10 |
![]() Join Date: Feb 2011
Reputation: 516
Posts: 764
|
I'm pretty sure the limitations will be similar to Stripper:source's add function. prop_physics_override will work, for instance, but no brush entities will be added at all.
I don't expect the commentary.txt to offer possibilities to remove or modify existing entities, so stripper is usually the better choice, if you have server control (but I guess that's exactly the point of this alternative). |
|
|
|
|
|
#11 | |
![]() Join Date: Feb 2012
Reputation: 0
Posts: 12
|
Quote:
What would be REALLY nice is if I was able to convert PC bsp files to 360 bsp map files. I'm not sure if this has already been done yet but in theory it seems like all you would need to do is take a PC bsp file and convert it from little-endian to big-endian and then compress it using LMZA. I think the compression and the endianess are the only differences between xbox bsp files and PC bsp files. Can anyone confirm this? I'm considering writing some tools to attempt these conversions. Seems odd that nobody has attempted this yet... The VMEX based bspsource tool can decompile xbox 360 compressed and big-endian encoded maps. It does the reverse of what I'm looking to do... I really wish it was able to recompile the xbox 360 compressed/big-endian maps. If I had the ability to convert PC bsp files to xbox formatted bsp files I could use Hammer (like all the PC users already can!!!) to modify existing 360 maps... therefore solving all my current problems and I wouldn't have to resort to all of these hackish tactics (commentary.txt & vscript) to change 360 maps. |
|
|
|
|
![]() |
|
||||||
| Thread Tools | |
| Display Modes | |
|
|