-
Notifications
You must be signed in to change notification settings - Fork 84
Scripts
-
Moved the anomaly_detector from
CBaseMonster
toCCustomMonster
, so that it could be used not only for mutants, but for stalkers too. If anyone doesn't know, this is an engine bypass of anomalies. By default it is used only for mutants in the state of rest.
** Also exported it for scripting. You can access it like this:
local anomaly_detector = obj:get_custom_monster():anomaly_detector()
log3( "Anomaly_Detect_Radius = %s", anomaly_detector.Anomaly_Detect_Radius )
log3( "Anomaly_Detect_Time_Remember = %s", anomaly_detector.Anomaly_Detect_Time_Remember )
log3( "is_active = %s", anomaly_detector.is_active )
anomaly_detector:activate()
anomaly_detector:deactivate()
-
Anomaly_Detect_Probability
setting added. This parameter defines the probability of bypassing a single anomaly. Default = 1, i.e. all anomalies are bypassed when anomaly_detector is active. -
Methods
activate()
anddeactivate()
have an argumentforce
(default false), which can be used to block the activity state. That is, ifactivate( true )
is called, anomaly_detector will be active untildeactivate( true )
is called and vice versa.activate()
is called when going to the idle state anddeactivate()
is called when leaving the idle state. That's what it does not disable scripted traversal or non-traversal of anomalies and need the specified argument. -
Added
CAnomalyDetector::remove_all_restrictions()
To make it remove all restrictions immediately. -
Added
CAnomalyDetector::remove_restriction( anom_id )
To remove information about only one anomaly. -
Added the ability to specify the bypass of anomalies created by artifact activation
This is determined by the fourth parameter in the
[artefact_spawn_zones]
section. If it is not present, nothing changes. Example:
; Artifacts that create anomalous zones when activated
; format: {artefact_section} = {zone_section}, radius, power[, eDefaultRestrictorTypeNone]
;
; eDefaultRestrictorTypeNone specifies that this anomaly should be bypassed by the
; by mobs. If this parameter does not exist, or is 0, this anomaly will not be bypassed by mobs
; will not be bypassed. If this parameter is 1, the anomaly will be bypassed.
[artefact_spawn_zones]
caps_mosquito_bald = amk_zone_mosquito_bald_average, 3.0, 1.3, 1
caps_gravi = amk_zone_gravi_zone_average, 3.0, 1.2, 1
caps_mincer = amk_zone_mincer_average, 3.5, 1.2, 1
caps_electra = amk_zone_witches_galantine_average, 4.0, 1.2, 1
caps_zharka = amk_zone_zharka_static_average, 2.0, 1.2, 1
caps_ameba = amk_zone_buzz_average, 1.5, 0.5, 1
caps_ice = amk_zone_ice_average, 4.0, 1.0, 1
- Added a clsid setting to bypass anomalies that never need to be bypassed. For example, if you add to the config of a mob
Anomaly_Detect_Ignore = zone_radioactive
then that mob will not bypass radioactive zones. Multiple clsid are set separated by commas.
- Exported
CPatrolPoint
andCPatrolPath
for scripts
-- Created a path with a single point that matches the actor's position. The add_point() method returns CPatrolPoint,
-- but it doesn't make much sense because it's a copy, so it doesn't make sense to change any properties in this copy,
-- since it will have no effect on the path.
local path = CPatrolPath()
local pp = path:add_point( db.actor:position() )
local pp = path:point( 0 ) -- Returns the first point of the path. Again, it is pointless to change its properties, since it is a copy.
local pp0 = CPatrolPoint() -- Created point
pp0.m_name = “name00” -- and give it a name.
pp0:position( db.actor:position() )
-- Assigned the current coordinates of the actor to it. The position() method will automatically calculate m_level_vertex_id and m_game_vertex_id
-- based on these coordinates. You can assign everything manually if you want:
pp0.m_position = db.actor:position()
pp0.m_level_vertex_id = db.actor:level_vertex_id()
pp0.m_game_vertex_id = db.actor:game_vertex_id()
pp0.flags = 0
-- These properties are also readable.
-- Now, the created and initialized point can be added to the path:
path:add_vertex( pp0 )
-- The path is ready to be used.
-
Added
obj:set_home( CPatrolPath, ... )
, which takesCPatrolPath
instead of the path name. The rest of its arguments are the same. -
Added an
at_home()
method that returns true/false if the mob is withinmax_radius
, andat_home( pos )
, which checks that pos is withinmax_radius
. - Added
level.patrol_path_add( patrol_name, CPatrolPath )
andlevel.patrol_path_remove( patrol_name )
level.patrol_path_add( patrol_name, CPatrolPath ) -- Registers a new path or replaces an existing path named patrol_name.
-- Paths added in this way should be deleted when deleting an actor, otherwise it will crash when exiting the game or loading a save.
level.patrol_path_remove( patrol_name ) -- Removes the path named patrol_name. Needed just to remove paths added via level.patrol_path_add().
Usage Examples:
db.test_path = CPatrolPath()
db.test_path:add_point( db.actor:position() )
local pp = db.test_path:point( 0 )
log3( "dsh: level_vertex_id = %s", pp.m_level_vertex_id )
log3( "dsh: test_path = %s", level.patrol_path_exists( "test_path" ) )
level.patrol_path_add( "test_path", db.test_path )
log3( "dsh: test_path = %s", level.patrol_path_exists( "test_path" ) )
local path = patrol( "test_path" )
log3( "dsh: level_vertex_id = %s", path:level_vertex_id( 0 ) )
level.patrol_path_remove( "test_path" )
** Spawn options added:**
** When the body is torn in the meat grinder (this is enabled by default in the engine, you don't even need to edit the configs).
Added parameters for anomalies:
; these are the online spawn settings
spawn_blowout_artefacts = on ; main switch for spawn option
artefact_spawn_probability = 0.05 ;the probability that an artifact will be born during the anomaly triggers
birth_on_death_probability = 0.2 ; probability that an artifact will be born after a creature dies in the anomaly.
birth_on_torn_probability = 0.5 ; probability of an artifact being born when the body is torn in a meat grinder.
birth_on_nonalive = true ; probability of birth when triggered by an item
birth_on_alive = true ; probability of birth when triggering on a living creature
birth_on_dead = true ; possibility of birth when triggering on corpse
Taken from here.
-
level.add_call(...)
now returns a control object that has a method:set_pause( ms )
. After using this method, the function specified inadd_call(...)
will be called inms
milliseconds. Here is the simplest example:
level.add_call(
function()
log3( "condition" )
return true
end,
function() log3( "action" ) end
):set_pause( 3000 )
After 3 seconds, it will be displayed:
condition
action
Here's a slightly more complicated example:
local lcall
local cnt = 10
lcall = level.add_call(
function()
log3( "condition" )
cnt = cnt - 1
lcall:set_pause( 1000 )
return cnt == 0
end,
function() end
)
Once started, it will be displayed 10 times:
condition
at a rate of once per second.
-
Finally fixed
level.remove_call(...)
Now it can be safely used even from a handler added vialevel.add_call(...)
. Handlers are not deleted by this call, but marked as deleted. They will be deleted in the processing loop, inupdate()
. - ** Also fixed
level.add_call(...)
view
level.add_call( self, self.condition, self.action )
ie. used for the object. level.remove_call(...)
also works with this form. level.remove_calls_for_object(...)
works correctly too.
How to use it. Like this:
local xvars = get_stored_vars()
xvars.test = 123
xvars.test2 = {}
xvars.test2.test1 = 456
It's simple, use it like a standard table. There are a couple of peculiarities. It is better to store only simple types: strings, numbers, tables, etc., including nested ones. Objects, vectors, time, etc., what is userdata, it is better not to use.
The second feature is lists. You don't need to do anything for direct access to list items, but if you want to work with this list like a real list, for example, to iterate it, or slip it into unpack(...)
, you need to turn it into a lua table. For example:
xvars.test = { 1, 2, 3 }
local t = xvars.test()
for i, v in ipairs( t ) do
end
The execute operation, i.e. ()
, returns a lua table that you can do whatever you want with. By default, the transformation is not recursive, i.e. it will not affect nested tables. To make it recursive, you need to do it like this:
local t = xvars.test( true )
i.e. pass an argument.
Essentially, CScriptZone
functionality has been added to CSpaceRestrictor
.
This is only needed for restrictors with logic that runs on the update. So by default, all restrictors do not execute the code that is needed for these callbacks to work. Especially since restrictors are such a thing, quite heavily used in the engine wilds, not sure that enabling these callbacks by default won't make things worse. To activate these callbacks, you need to do the following.
This is an example from the restrictors script binder, in net_spawn()
:
self.object:set_callback( callback.zone_enter, self.on_enter, self )
self.object:set_callback( callback.zone_exit, self.on_exit, self )
self.object:get_space_restrictor():schedule_register()
This will be followed by calls of
function restrictor_binder:on_enter( zone, obj )
end
function restrictor_binder:on_exit( zone, obj )
end
Here, zone is self.object
and obj
is what got into or left the restrictor.
For optimization and again, from the point of view of restrictors with logic, callbacks are only called for living things. After all, the logic usually uses on_actor_inside
and on_npc_in_zone
or whatever it is, basically checking if an actor or mobs hit the restrictor. So what's the point of pulling callbacks unnecessarily because of some light bulb that's in the restrictor. If and when needed, you can make it customizable.
Added a few more script methods:
schedule_unregister() -- disables code that say scans the perimeter of the restrictor. The method is the inverse of schedule_register().
is_scheduled() -- returns the status of this scan.
active_contact( id ) -- returns if the object with the passed id is inside the restrictor.
All this only works if the scan was enabled via schedule_register()
.
Sample script to use:
log1(“texture_find test for name: act\\\act_arm_perchatka_cs”)
local t1 = texture_find(“act\\\\act_arm_perchatka_cs”) -- returns table: key texture name, value object
if t1 then
local tex = t1[ “act\\\act_arm_perchatka_cs” ] ]
log1(“found, name=” ... tex:get_name())
local name = “act\\\\act_arm_perchatka_cs_black”
tex:load(name) -- With this replacement method the texture will be replaced wherever it is used.
end
Search for textures by mask:
log1(“texture_find test for name: act\\\act_arm_perchatka_cs*”)
local t1 = texture_find(“act\\\\act_arm_perchatka_cs*”) -- returns table: key texture name, value object
if t1 then
for n, t in pairs(t1) do
log1(“found, name=” ... t:get_name())
end
end
- Added
demo_record
script control:
level.demo_record_start()
level.demo_record_stop()
local HPB = level.demo_record_get_HPB()
level.demo_record_set_HPB(HPB)
-- direction
-- HPB.x Left\Right
-- HPB.y Up\Down
-- HPB.z Rotate Left\Rotate Right
local position = level.demo_record_get_position()
level.demo_record_set_position(position)
-- position x y z as usual on the level
level.demo_record_set_direct_input(true/false) -- direct input control
Also corrected game control in demo_record
mode. Turns on by *
(asterisk DIK_MULTIPLY
)
- PPE effects should now be displayed in 3rd-person mode. Also added
g_effects_on_demorecord
command to display effects indemo_record
mode.
key_state(DIK_Keys.DIK_RETURN)
The IReader and IWriter classes, which are used to read and write binary files, have been fixed and exported.
-- Reading a binary file
local file = getFS():r_open(file_path)
file:open_chunk(0)
local value1 = file:r_u32()
local value2 = file:r_stringZ()
file:close_chunk()
getFS():r_close(file)
-- Writing a binary file
local file = getFS():w_open(file_path)
file:open_chunk(0)
file:w_u32(value1)
file:w_stringZ(value2)
file:close_chunk()
getFS():w_close(file)
- Added script exports from X-Ray Extensions. There is no sense to document them here, because there are too many of them. It is better to see all exports either in sources or in lua_help.
- Other exports, added in OGSR Engine:
-- Lock key presses
level.block_action(key_bindings.kTORCH)
level.unblock_action(key_bindings.kTORCH)
--Flag on mobs to enable invisibility for anomalies
obj:get_custom_monster().visible_for_zones = false --Anomalies will not trigger if this mob hits them.
--Returns the number of rounds in the hidden part. I.e. if the weapon is currently in stun mode, then the ammo information
-- is in the hidden part and vice versa. This method returns the number of cartridges if the weapon is in underbarrel mode. In this
-- case the already existing :get_ammo_in_magazine() returns the number of rounds in the underbarrel.
obj:get_ammo_in_magazine2()
obj:get_hud_item_state() -- Returns the current state of the item's hud. You can use the corresponding global_flags:
weapon_states = {
idle = global_flags.eIdle,
fire = global_flags.eFire,
fire2 = global_flags.eFire2,
reload = global_flags.eReload,
showing = global_flags.eShowing,
hiding = global_flags.eHiding,
hidden = global_flags.eHidden,
misfire = global_flags.eMisfire,
mag_empty = global_flags.eMagEmpty,
switch = global_flags.eSwitch,
}
obj:radius() -- Returns the movable radius of the object.
-- This is a simplified analog from x-ray extensions, no callbacks or blackjack. I thought it was possible to use play_cycle(), but
-- no, play_cycle() starts the model animation, and I needed to start the hud animation.
obj:play_hud_animation( anim_name, bool_mix_in )
sobj.m_level_vertex_id , sobj.m_game_vertex_id -- Now available for writing.
sobj.m_flags -- Contains Flags32 with server flags. These are UsedAI_Locations, etc.
sobj.level_id -- level id of this object
sobj.level_name -- The level name of this object
sobj.is_alive -- True is alive mob, false is not alive or not a mob at all.
sobj.set_position( pos ) -- Sets the new position of the object.
sobj.cse_get_restrictor_type() -- For restrictors, returns its type (u8)
for id, sobj in alife():objects() do -- Loop through all server objects in the game
-- !!!Never delete/spawn objects inside the loop!!!!
end
alife():remove_in_restrictions( sobj ) -- To clear in-restrictors (added to bypass anomalies, for example)
alife():remove_out_restrictions( sobj ) -- To clean out-restrictors
-- Redraws the inventory or search window. Makes sense to use if an open inventory has changed the state of an item, such as condition, which should cause the item to be rearranged.
-- items. Unless update_inventory_window() is executed, the changes will only be visible the next time the inventory is opened.
update_inventory_window()
-- Exported main game window class with GetStatic method. You can, for example, hide minicard:
local wnd = get_main_window()
local st = wnd:GetStatic( "minimap:background" )
if st then
local r = Frect()
st:GetWndRect( r )
log3("~~ [minimap:background] rect = { %.1f, %.1f, %.1f, %.1f }", r.x1, r.y1, r.x2, r.y2 )
r.x1 = -1000
st:SetWndRect( r )
end
alife().loaded_save_name -- the name of the loaded save.
alife().save_name -- the name of the last loaded save.
local obj = db.actor:object( "wpn_addon_scope" )
-- The weapon in your hands will be attached by an PSO-1, which should be in your inventory. The second argument shows whether the addon should be removed from the inventory or not.
db.actor:active_item():get_weapon_m():attach_addon( obj:get_inventory_item(), false )
-- Reverse situation. Will detach the PSO-1 from the active weapon. The second argument shows whether the scope should be spun into inventory or not.
db.actor:active_item():get_weapon_m():detach_addon( "wpn_addon_scope", false )
db.actor.conditions:fdelta_time() -- Returns the number of game seconds (float) since the last update. This is the time
-- is used when calculating the work of artifacts on the belt and when calculating changes in the actor's parameters: health, satiety, etc.
db.actor.conditions.has_valid_time -- bool Indicates that fdelta_time() will return the correct time. You should always check this before using
-- fdelta_time() you should always check this. The issue is that the scripted update is called before conditions updates.
-- Because of this, on the very first scripted update fdelta_time() will return garbage, in my case it was a very large number.
sobj:get_inventory_item().item_condition -- Access the item's state through a server object.
CUIWindow:GetCUIStatic() -- New method to get CUIStatic from CUIWindow
level.get_change_level_wnd() -- Returns the level change confirmation window. It is created once and is reused.
level.change_level( game_vertex_id, level_vertex_id, pos, dir ) -- Changes level. It's like to add level_changer on actor position but without the extra steps.
-- Added sobj:get_space_restrictor() to access CSE_ALifeSpaceRestrictor
-- Currently can:
local sr = sobj:get_space_restrictor()
log3( "m_space_restrictor_type = %d", sr.restrictor_type )
-- It's writable, too. So that you don't have to access this property through a netpackage.
-- Useful if some anomaly needs to change its restrictor type.
-- For example, to make CAnomalyDetector ignore it.
-- Exported direct access to CSE_ALifeItemWeapon:
local s_wpn = sobj:get_weapon()
-- Read/write accesses:
s_wpn.ammo_current
s_wpn.ammo_elapsed
s_wpn.weapon_state
s_wpn.addon_flags
s_wpn.ammo_type
sobj.custom_data -- Direct access to custom data
local trader = sobj:get_trader() -- Direct access to trader properties in the nepis
log3(“money = %d”, trader.money ) -- read/write
log3(“character_name = %s”, trader.character_name ) -- read only
-- Added the ability to directly modify custom_data via spawn_ini()
-- Here is an example of how to use it:
local ini = sobj:spawn_ini()
ini.readonly = false
ini:w_string( "test", "dsh_test", "123" )
sobj:save_spawn_ini()
log3( "custom_data = %s", sobj.custom_data )
-- You must be sure to clear the “readonly” checkbox before changing, otherwise ASSERT() will be triggered,
-- since modification is forbidden by default. You can then use the remove_line, w_bool, w_string, w_u32, w_s32 methods,
-- w_float, w_vector.
-- Well, at the end you need to save the changes back to custom_data. This is done by sobj:save_spawn_ini().
ini:get_as_string() -- Returns ini as a string
ini:remove_section(“section_name” ) -- Removes a section
-- Added a section iterator for CScriptIniFile. Example usage:
system_ini():iterate_sections(function(sect)
local cls = system_ini():r_clsid(sect, “class”)
if cls and cls == clsid.equ_stalker_s then
...
end
end)
level.set_cam_inert( float ) -- to change cam_inert directly
-- This is in addition to the already existing sobj:brain():can_choose_alife_tasks( bool )
sobj:brain():can_choose_alife_tasks() -- bool to get state
sobj:brain().m_time_interval -- u32 How often to offer free mobs to smarthings
sobj:brain().m_last_search_time -- u32 When it was last done.
obj:is_relation_enemy( obj2 ) -- This is analogous to checking obj.relation( obj2 ) == game_object.enemy or obj.relation( obj2 ) == game_object.worst_enemy
-- In scripts, worst_enemy is not checked anywhere. It's true that it's not a fact that someone uses -2 in [monster_relations].
level.set_monster_relation( from, to, rel ) -- This function allows you to change mutant relationships,
-- i.e. what is described in the [monster_relations] section of game_relations.ltx. Example usage:
level.set_monster_relation(“rat”, “actor”, 0 ) -- make rats neutral to the actor
level.set_monster_relation(“rat”, “actor”, -1 ) -- make rats enemies of the actor.
-----------------------------------------------------------------------------
npc:ambush_cover( npc_pos, enemy_pos, radius, min_distance ) -- Must find a vertex within radius radius of npc_pos that is at least min_distance and maximally covered on the enemy_pos side and minimally on the npc_pos side.
npc:angle_cover( pos, radius, enemy_pos, min_enemy_distance, max_enemy_distance, enemy_vertex_id )
-- Added scripted filtering capability to all npc:*_cover(...) methods. Example usage:
local cover_cache = {}
local cover_callback = function( cover )
local cover_vertex = cover:level_vertex_id()
local cached = cover_cache[ cover_vertex ]
if cached ~= nil then return cached end
cover_cache[ cover_vertex ] = not (
check_vertex_locked( npc, cover_vertex )
or its_a_trap( npc, cover_vertex )
)
return cover_cache[ cover_vertex ]
end
local cover = npc:angle_cover( npc_pos, r, enemy_pos, min, max, enemy:level_vertex_id(), cover_callback )
-- I.e. the last parameter can be passed to a function that, in the parameters
-- takes cover_point and returns true/false, indicating to the engine that
-- this cover can or cannot be used in this case.
-----------------------------------------------------------------------------
update_inventory_weight() -- Updates only the static weights in the inventory.
-- If update_inventory_window() is used, it causes not only the weight statics to be updated,
-- but also causes the item icons to jump if there is free space.
-- For example, if we put something on our belt or remove it from our belt.
callback.zone_enter, callback.zone_exit -- Callbacks for anomalies to enter and exit the zone.
-- The arguments are passed the client objects of the anomaly itself and the object that entered or exited.
relation_registry.clear_personal_relations( id ) -- To clear the relation registry of a mob with this id.
level.valid_vertex_id( u32 ) -- Checks the passed level_vertex_id for validity and returns the corresponding bool.
level.is_accessible_vertex_id( u32 ) -- Checks not only that the vertex exists as level.valid_vertex_id( u32 ), but also that it is not locked.
level.vertex_count() -- u32 Returns the number of vertexes at the current location.
level.disable_vertex( u32 ) -- To block this level_vertex. That is, mobs will bypass it as if there were a restrictor prohibiting them from entering it.
level.enable_vertex( u32 ) -- Reverse method
cross_table():vertex( u32 ):game_vertex_id() -- For a passed level_vertex_id, returns its corresponding game_vertex_id(). Of course this only works for the current location.
-- For a complete renaming of the hero, you need to do:
db.actor:get_inventory_owner():SetName(“Shooter” )
local sobj = db.actor:get_alife_object()
local trader = sobj:get_trader()
trader.character_name = “Shooter”
-- Some places in the engine use the name from InventoryOwner, and others use the name from CSE_AlifeTraderAbstract.
sobj:get_weapon_gl().ammo_type_2 -- Get/change the type of hidden charges
sobj:get_weapon_gl().ammo_elapsed_2 -- Get/change the number of hidden charges.
--Similar to iterate_inventory methods added:
obj:iterate_belt(func, obj) -- Retrieve items on belt
obj:iterate_ruck(func, obj) -- Retrieve items in backpack
CUIWindow:GetPosLeft() -- Returns m_wndPos.x from CUIWindow
CUIWindow:GetPosTop() -- Returns m_wndPos.y from CUIWindow
CUIWindow:DetachAll() -- Deletes all attached windows to a CUIWindow.
CUIStatic:EnableHeading() -- Allows the original static aspect ratio to be preserved at any screen resolution.
obj:get_inventory_item().always_ungroupable = true -- Set an item to be unconditionally ungroupable in inventory
obj:get_physics_shell():set_dynamic_ignore() -- Do this no sooner than the first adait of this object. The phys object will become permeable to mobs as corpses when collision with them is disabled.
obj:get_physics_shell():set_ignore_static() -- Enables this object to ignore static.
-----------------------------------------------------------------------------
---Added the ability to use the Feel::Touch engine with any game object from scripts
class “feel_touch”
function feel_touch:__init( obj )
self.object = obj
-- activates the engine Feel::Touch for this object. The first argument is the radius in which to detect the appearance or
-- disappearance of objects. The second argument is what will be passed by the first argument to subsequent functions.
-- The next two arguments are pointers to the functions below.
self.object:add_feel_touch( 5, self, self.feel_touch_new_delete, self.feel_touch_contact )
end
-- The function will be called when a new object appears in the radius or disappears.
-- The client object and a flag indicating that the object has appeared (true) or disappeared (false) will be passed.
function feel_touch:feel_touch_new_delete( obj, bool_is_new )
log3( “%s: %s %s %s”, self.object:name(), obj:name(), ( is_new and “detected” or “gone” ) ))
end
-- The function is called for each new object and the result determines whether or not to track the object.
-- If this function is not specified, any mobs will be processed.
function feel_touch:feel_touch_contact( obj )
return obj:is_actor()
end
function feel_touch:shutdown()
-- Deactivates the Feel::Touch engine for this object. Make sure to call it when it is no longer needed.
-- Arguments are the same as add_feel_touch() except for the radius.
self.object:remove_feel_touch( self, self.feel_touch_new_delete, self.feel_touch_contact )
end
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- These methods force the non-dude to grab the object:
npc:ph_capture_object( obj )
npc:ph_capture_object( obj, capture_bone )
npc:ph_capture_object( obj, bone )
npc:ph_capture_object( obj, bone, capture_bone )
--[=[
Here:
capture_bone is the name of the bone the non-species will use to hold obj. If not specified, it is taken from the custom_data of the visual of this non-specie. Usually there is bip01_tail.
bone - id of the obj's bone, which will be used to hold obj. If not specified, the bone closest to capture_bone will be used.
--]=]
npc:ph_release_object() -- releases the obj.
local cap = npc:ph_capture() -- returns an instance of CPHCapture, i.e. you can check if the object is captured or not.
-- cap will have read/write accessible properties “capture_force”, “distance”, “pull_distance” and “time_limit”. These properties are the same as specified in the visual's custom_data, in the [capture] section.
cap.pull_force -- corresponds to the setting from the custom_data of the visual, i.e. this is the force with which the object is pulled when captured.
cap.hard_mode -- whether the item is not allowed to fall out when dragged. It is on by default for the actor, off for all others.
cap.e_state -- Shows the current capture mode. Takes the following values:
ph_capture.pulling
ph_capture.captured
ph_capture.released
-----------------------------------------------------------------------------
obj:disable_anomaly( bool_keep_update ) -- now accepts an optional argument that indicates to keep calling the update when the anomaly is disabled.
sobj.angle, sobj.position --The properties are readable and writable. You can change the direction and position of an object directly, without perversion with netpackages.
level.get_current_ray_query() -- Get the current skinny raytrace. Can be used to get details about the object/static the actor is looking at.
obj:get_weapon().scope_lense_fov_factor -- For scripting magnification settings in 3D scopes.
-----------------------------------------------------------------------------
level.iterate_vertices_inside( P, R, partially_inside, func ) -- Calls func( lvid ) for each vertex that is within radius R of position P. Parṫtially_inside specifies that vertexes can be partially inside the radius. If false, only those vertexes that are entirely inside will be taken.
--Example:
local vertexes = {}
level.iterate_vertices_inside( around_pos, radius, false, function( lvid ) table.insert( vertexes, lvid ) end )
--In this case, the list of vertexes will contain vertexes that are entirely inside the radius of the around_pos position.
level.iterate_vertices_border( P, R, func ) --Does the same thing, except it looks for vertexes that are located around the perimeter of the radius. That is, those that are partially inside and yet not completely inside.
-----------------------------------------------------------------------------
local icon_p = CIconParams( section )
icon_p:set_shader( b ) -- Sets the statics b the correct texture to display the item icon with section. If there is an icon_name in that section, uses it, if not, takes it from the corresponding canvas.
--In addition, the following properties are readable:
icon_p.icon_group
icon_p.grid_width
icon_p.grid_height
icon_p.grid_x
icon_p.grid_y
icon_p.icon_name
--Example:
self.item_icon = CUIStatic() --Created a static for the item icon
self.item_icon:SetAutoDelete( true )
CIconParams( ui_item.data.section ):set_shader( self.item_icon ) --Read the icon from the item section and place it on the statick
self:AttachChild( self.item_icon ) --Do something further with this static...
obj:explode_initiator( id ) -- Detonates the explosive with the culprit. id is the id of the culprit on whose behalf the explosion will hit.
-----------------------------------------------------------------------------
-- This is how you can get an NPC to throw a grenade:
local obj = npc:object(“grenade_f1” )
if npc:throw_target( db.actor:position(), db.actor ) then
npc:set_item( object.fire1, obj )
end
--[=[
throw_target() -- returns true/false, which shows the result of the check, i.e. whether the grenade will reach the position or hit an obstacle earlier. The method can have the following form:
throw_target( pos, obj )
throw_target( pos, level_vertex_id, obj )
pos - position where to throw the grenade
obj - enemy that will not be considered an obstacle when checking the trajectory
level_vertex_id - shift the position by a random value from two to six meters relative to this vertex
--]=]
-----------------------------------------------------------------------------
obj:add_wounds( hit_power, hit_type, u16_element ) -- Open bleed on a mob
obj:unload_magazine(true, true) -- The first argument is whether to unload ammo to the owner, the second argument is whether to unload the PG, if any.
npc:calculate_item_price(item, bool_buying) -- Allows you to get the price for a merchant to buy or sell an item from an actor.
-- item is the client object of the item
-- bool_buying - buy or sell flag
obj:controller_psy_hit_active() -- bool Check returns whether the controller is currently being attacked or not. This is when it is attracting to itself. obj is the client object of the controller.
-- Added a script method drop_item_and_throw(), which throws an item from inventory in the specified increment. Example usage:
local dir = vector_rotate_y( db.actor:direction(), 180 )
if ( dir.y < 0 ) then dir.y = -dir.y end
dir:normalize():mul( 2 )
db.actor:drop_item_and_throw( obj, dir )
-----------------------------------------------------------------------------
-- The optional disp_base parameter in the stalker section means its initial dispersion when firing, to which the other disp_* dispersions are already added. By default it is zero, i.e. it has no effect. It can be changed by scripting methods:
local disp_base = npc:stalker_disp_base() -- Returns the current value.
npc:stalker_disp_base( 0.1 ) -- Sets the current value.
npc:stalker_disp_base( range, maxr ) -- Calculates and sets the current value. range is the distance to the target, maxr is the maximum distance from the aiming point where the bullet can miss. I.e. dispersion is set so that at this distance it would be possible to miss no more than maxr.
-----------------------------------------------------------------------------
-- Added export of clsid_table (table) to global space. Example of use:
For name, clsid in pairs(_G.clsid_table) do
log1(“--Name: [”...name...“] clsid: [”...clsid...“]”)")
end
-----------------------------------------------------------------------------
-- Added exports for engine psHUD_Flags - level.get_hud_flags() and for HUD().GetUI()->GameIndicatorsShown() - level.game_indicators_shown().
-- Constants to add to _g.script (haven't done an export yet):
HUD_CROSSHAIR = 1 * 2 ^ 0
HUD_CROSSHAIR_DIST = 1 * 2 ^ 1
HUD_WEAPON = 1 * 2 ^ 2
HUD_INFO = 1 * 2 ^ 3
HUD_DRAW = 1 * 2 ^ 4
HUD_CROSSHAIR_RT = 1 * 2 ^ 5
HUD_WEAPON_RT = 1 * 2 ^ 6
HUD_CROSSHAIR_DYNAMIC = 1 * 2 ^ 7
HUD_CROSSHAIR_RT2 = 1 * 2 ^ 9
HUD_DRAW_RT = 1 * 2 ^ 10
HUD_CROSSHAIR_BUILD = 1 * 2 ^ 11
-- Normal (engine copy) way to check if the game is showing hud:
function hud_present()
return level.game_indicators_shown() and level.get_hud_flags():is(bit_or(HUD_DRAW, HUD_DRAW_RT))
end
-----------------------------------------------------------------------------
-- The checks can be useful for net_destroy\on_unregister to check if it is an object being deleted or a level being unloaded:
alife():is_unloading() -- bool when server objects are unloaded
level.is_removing_objects() -- bool when client objects are unloaded
npc:see_right_now( obj ) -- bool Similar to npc:see( obj ), which checks if this object is visible right now or not. see() checks if obj is in visual memory.
-- Custom statics can now just be hidden and shown back:
hud():GetCustomStatic( “xxx” ):wnd():Show( false ) -- hide
-- and true when you need to show. That is, you can AddCustomStatic() everything you need once, and then hide and show as needed, instead of removing and adding back.
level.nearest_vertex_id( Fvector ) -- Returns the nearest vertex to this position. Uses a blunt enumeration of all vertexes.
-- Callback for the `trade_perform_operation` actor:
self.object:set_callback( callback.trade_perform_operation, self.trade_perform_operation, self )
-- ...
function actor_binder:trade_perform_operation( trader, money_out, money_in )
-- trader is who the actor traded with.
-- money_out and money_in is how much money the actor gave to the trader and how much he received.
end
level.get_character_community_team(“comm” ) -- returns the team corresponding to the specified faction. This team can be used in obj:change_team(), for example.
npc:can_fire_to_enemy( enemy ) -- will return true or false depending on whether or not the enemy can currently be fired with the current weapon. If you can, you can call object.fire1. If not, only object.aim1.
-- You can shoot if:
-- A non-specimen sees an enemy or the enemy is in the line of fire
-- If the head is turned in the direction of the enemy
-- If there is an obstacle in the line of fire, it must not be closer than 2.5 meters from the non-person and must be closer to the enemy than to the non-person.
obj:set_money( money ) -- A method to set money for the non-people and the actor as well.
obj:register_in_combat() / obj:unregister_in_combat() -- combat_planner does this when entering and exiting combat.
obj:is_exploded() --Returns true if the explosives have already exploded, but the client object still exists.
obj:is_ready_to_explode() --Returns true when the explosives begin to explode.
npc:remove_memory_object( obj ) --Method for removing an obj object from npc memory.
--Exported the swing effector into scripts:
local eff = level.get_effector_bobbing()
-- The following properties are available:
eff.run_amplitude
eff.walk_amplitude
eff.limp_amplitude
eff.run_speed
eff.walk_speed
eff.limp_speed
-- Methods to disallow/allow calling console commands. Commands that are called from scripts via get_console():execute(...) are not affected by this prohibition.
get_console():disable_command(“name”)
get_console():enable_command(“name”)
alife():spawn_id(“name” ) --Returns `spawn_id` from `all.spawn` by object name. When rebuilding allspawn spawn_id constantly change, and they have to change them after each rebuild in the scripts. And so nothing to change will not need to change.
db.actor.inventory:is_active_slot_blocked() --bool Check for blocking a slot (for example, on the stairs and so on).
db.actor:active_item():get_weapon():UseScopeTexture() -- shows if the weapon is currently using texture scope.
-- One more argument is passed to the `article_info` script callback, the text of the article.
self:AddCallback(
“control_”..opt,
ui_events.TRACKBAR_CHANGED, --New callback to change the position of the trakbar.
function()
--log('TRACKBAR_CHANGED(%s) : %3.3f', opt, ctl:GetTrackValue()) ---New method to get the trakbar position
end
)
-- Added `PlaySound(“filename”)` method to the menu class.
snd_obj:set_start_time(0.5) -- added method for sound_object to set the start position of the sound
sobj.visual_name = “new_visual” -- for server objects that have a visual, this is how you can read/change the name of the visual.
-- Ability to open read/write ltx files in any directory: --
local setting_ini = ini_file(full_name, false) -- false is needed here, so the file will be searched as specified, without being bound to configs.
setting_ini.readonly = false -- mandatory on save
setting_ini:w_string(“setting”, “string_param”, “string_value123”)
setting_ini:w_bool(“setting”, “bool_param”, true)
setting_ini:w_float(“setting”, “float_param”, 123.123)
setting_ini:save()
----------------------------------------------------------------------------
sobj:set_health(0.5) -- you can change the health of a server object
obj:setVisible(false) -- disable client object rendering, you can hide objects this way
local slot_n = obj:get_slot() -- returns the slot number (u8) this item is in.
-- Added `FS.FS_NoLower` flag so that file_list_open_ex does not lowercase file names.
local flist = getFS():file_list_open_ex(“$game_saves$”, FS.FS_ListFiles + FS.FS_ClampExt + FS.FS_RootOnly + FS.FS_NoLower, “*.sav” )
flist:Sort(FS.FS_sort_by_modif_down)
for file in flist:GetAll() do
wnd:AddItemToList( file:NameFull(), file:Modif() )
end
-- Added a third argument to sound_object to play sound as music (in fact, only the volume will be adjusted via the music volume slider in the menu). Values: `sound_object.effect` (default) and `sound_object.music`.
local snd = sound_object(path, 0, sound_object.music)
-- Export `CMainMenu:IsActive()` -- not sure why this is needed, but let it be
-- Added `entity_alive_before_hit` callback for `CCar` & `CHelicopter` classes
-- Added `level.iterate_nearest` method and `on_footstep`, `on_actor_land`, `on_actor_jump` callbacks from Anomaly
-- New scripting methods for the lamp class:
local lamp = self.object:get_hanging_lamp()
lamp:set_volumetric( true )
lamp:set_volumetric_quality( 0.9 )
lamp:set_volumetric_intensity( 0.05 )
lamp:set_volumetric_distance( 0.3 )
-- Extended the class of scripted particles. Added `set_position`, `set_direction`, `set_orientation`, `last_position` methods from Anomaly and added the ability to play particles in hud mode: `:play(true)` / `:play_at_pos(pos, true)`.
-- Added export of `level.is_ray_intersect_sphere` function to scripts to check if a ray intersects a sphere:
function is_actor_looking_to_pos( pos, radius )
return level.is_ray_intersect_sphere( device().cam_pos, device().cam_dir, pos, radius ) >= 0
end
--For example, check if the actor is looking in an area with radius 0.5 from object:position()
local looking = is_actor_looking_to_pos( object:position(), 0.5 )