2701 lines
57 KiB
C++
2701 lines
57 KiB
C++
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Logfile:: /EF2/Code/DLLs/game/scriptslave.cpp $
|
|
// $Revision:: 64 $
|
|
// $Author:: Singlis $
|
|
// $Date:: 9/26/03 2:36p $
|
|
//
|
|
// Copyright (C) 1997 by Ritual Entertainment, Inc.
|
|
// All rights reserved.
|
|
//
|
|
// This source is may not be distributed and/or modified without
|
|
// expressly written permission by Ritual Entertainment, Inc.
|
|
//
|
|
|
|
//
|
|
// DESCRIPTION:
|
|
// Standard scripted objects. Controlled by ScriptThread. These objects
|
|
// are bmodel objects created in the editor and controlled by an external
|
|
// text based script. Commands are interpretted on by one and executed
|
|
// upon a signal from the script master. The base script object can
|
|
// perform several different relative and specific rotations and translations
|
|
// and can cause other parts of the script to be executed when touched, damaged,
|
|
// touched, or used.
|
|
//
|
|
|
|
#include "_pch_cpp.h"
|
|
#include "class.h"
|
|
#include "mover.h"
|
|
#include "scriptmaster.h"
|
|
#include "scriptslave.h"
|
|
#include "sentient.h"
|
|
#include "item.h"
|
|
#include "gibs.h"
|
|
#include "explosion.h"
|
|
#include "equipment.h"
|
|
#include <qcommon/gameplaymanager.h>
|
|
|
|
/*****************************************************************************/
|
|
/*QUAKED script_object (0 0.5 1) ? NOT_SOLID
|
|
|
|
******************************************************************************/
|
|
|
|
Event EV_ScriptSlave_DoMove
|
|
(
|
|
"processCommands",
|
|
EV_CODEONLY,
|
|
NULL,
|
|
NULL,
|
|
"Move the script slave."
|
|
);
|
|
Event EV_ScriptSlave_NewOrders
|
|
(
|
|
"newOrders",
|
|
EV_CODEONLY,
|
|
NULL,
|
|
NULL,
|
|
"Inform script that it is about to get new orders."
|
|
);
|
|
Event EV_ScriptSlave_Angles
|
|
(
|
|
"angles",
|
|
EV_SCRIPTONLY,
|
|
"v",
|
|
"angles",
|
|
"Sets the angles."
|
|
);
|
|
Event EV_ScriptSlave_Trigger
|
|
(
|
|
"trigger",
|
|
EV_SCRIPTONLY,
|
|
"s",
|
|
"entname",
|
|
"Trigger entities target."
|
|
);
|
|
Event EV_ScriptSlave_Next
|
|
(
|
|
"next",
|
|
EV_DEFAULT,
|
|
NULL,
|
|
NULL,
|
|
"Goto the next waypoint."
|
|
);
|
|
Event EV_ScriptSlave_JumpTo
|
|
(
|
|
"jumpto",
|
|
EV_SCRIPTONLY,
|
|
"sFF",
|
|
"vector_or_entity token token",
|
|
"Jump to specified vector or entity."
|
|
);
|
|
Event EV_ScriptSlave_MoveTo
|
|
(
|
|
"moveto",
|
|
EV_SCRIPTONLY,
|
|
"e",
|
|
"entity_to_move_to",
|
|
"Move to the specified entity."
|
|
);
|
|
Event EV_ScriptSlave_MoveToPosition
|
|
(
|
|
"movetopos",
|
|
EV_SCRIPTONLY,
|
|
"v",
|
|
"position",
|
|
"Move to the specified position."
|
|
);
|
|
Event EV_ScriptSlave_Speed
|
|
(
|
|
"speed",
|
|
EV_DEFAULT,
|
|
"f",
|
|
"speed",
|
|
"Sets the speed."
|
|
);
|
|
Event EV_ScriptSlave_Time
|
|
(
|
|
"time",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"travel_time",
|
|
"Sets the travel time."
|
|
);
|
|
Event EV_ScriptSlave_MoveUp
|
|
(
|
|
"moveUp",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"dist",
|
|
"Move the position up."
|
|
);
|
|
Event EV_ScriptSlave_MoveDown
|
|
(
|
|
"moveDown",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"dist",
|
|
"Move the position down."
|
|
);
|
|
Event EV_ScriptSlave_MoveNorth
|
|
(
|
|
"moveNorth",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"dist",
|
|
"Move the position north."
|
|
);
|
|
Event EV_ScriptSlave_MoveSouth
|
|
(
|
|
"moveSouth",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"dist",
|
|
"Move the position south."
|
|
);
|
|
Event EV_ScriptSlave_MoveEast
|
|
(
|
|
"moveEast",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"dist",
|
|
"Move the position east."
|
|
);
|
|
Event EV_ScriptSlave_MoveWest
|
|
(
|
|
"moveWest",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"dist",
|
|
"Move the position west."
|
|
);
|
|
Event EV_ScriptSlave_MoveForward
|
|
(
|
|
"moveForward",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"dist",
|
|
"Move the position forward."
|
|
);
|
|
Event EV_ScriptSlave_MoveBackward
|
|
(
|
|
"moveBackward",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"dist",
|
|
"Move the position backward."
|
|
);
|
|
Event EV_ScriptSlave_MoveLeft
|
|
(
|
|
"moveLeft",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"dist",
|
|
"Move the position left."
|
|
);
|
|
Event EV_ScriptSlave_MoveRight
|
|
(
|
|
"moveRight",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"dist",
|
|
"Move the position right."
|
|
);
|
|
Event EV_ScriptSlave_RotateXDownTo
|
|
(
|
|
"rotateXdownto",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the x down to angle."
|
|
);
|
|
Event EV_ScriptSlave_RotateYDownTo
|
|
(
|
|
"rotateYdownto",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the y down to angle."
|
|
);
|
|
Event EV_ScriptSlave_RotateZDownTo
|
|
(
|
|
"rotateZdownto",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the z down to angle."
|
|
);
|
|
Event EV_ScriptSlave_RotateAxisDownTo
|
|
(
|
|
"rotateaxisdownto",
|
|
EV_SCRIPTONLY,
|
|
"if",
|
|
"axis angle",
|
|
"Rotate the specified axis down to angle."
|
|
);
|
|
Event EV_ScriptSlave_RotateXUpTo
|
|
(
|
|
"rotateXupto",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the x up to angle."
|
|
);
|
|
Event EV_ScriptSlave_RotateYUpTo
|
|
(
|
|
"rotateYupto",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the y up to angle."
|
|
);
|
|
Event EV_ScriptSlave_RotateZUpTo
|
|
(
|
|
"rotateZupto",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the z up to angle."
|
|
);
|
|
Event EV_ScriptSlave_RotateAxisUpTo
|
|
(
|
|
"rotateaxisupto",
|
|
EV_SCRIPTONLY,
|
|
"if",
|
|
"axis angle",
|
|
"Rotate the specified axis up to angle."
|
|
);
|
|
Event EV_ScriptSlave_RotateXDown
|
|
(
|
|
"rotateXdown",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the x down by the specified amount."
|
|
);
|
|
Event EV_ScriptSlave_RotateYDown
|
|
(
|
|
"rotateYdown",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the y down by the specified amount."
|
|
);
|
|
Event EV_ScriptSlave_RotateZDown
|
|
(
|
|
"rotateZdown",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the z down by the specified amount."
|
|
);
|
|
Event EV_ScriptSlave_RotateAxisDown
|
|
(
|
|
"rotateaxisdown",
|
|
EV_SCRIPTONLY,
|
|
"if",
|
|
"axis angle",
|
|
"Rotate the specified axis down by the specified amount."
|
|
);
|
|
Event EV_ScriptSlave_RotateXUp
|
|
(
|
|
"rotateXup",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the x up by the specified amount."
|
|
);
|
|
Event EV_ScriptSlave_RotateYUp
|
|
(
|
|
"rotateYup",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the y up by the specified amount."
|
|
);
|
|
Event EV_ScriptSlave_RotateZUp
|
|
(
|
|
"rotateZup",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"angle",
|
|
"Rotate the z up by the specified amount."
|
|
);
|
|
Event EV_ScriptSlave_RotateAxisUp
|
|
(
|
|
"rotateaxisup",
|
|
EV_SCRIPTONLY,
|
|
"if",
|
|
"axis angle",
|
|
"Rotate the specified axis up by the specified amount."
|
|
);
|
|
Event EV_ScriptSlave_RotateX
|
|
(
|
|
"rotateX",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"avelocity",
|
|
"Rotate about the x axis at the specified angular velocity."
|
|
);
|
|
Event EV_ScriptSlave_RotateY
|
|
(
|
|
"rotateY",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"avelocity",
|
|
"Rotate about the y axis at the specified angular velocity."
|
|
);
|
|
Event EV_ScriptSlave_RotateZ
|
|
(
|
|
"rotateZ",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"avelocity",
|
|
"Rotate about the z axis at the specified angular velocity."
|
|
);
|
|
Event EV_ScriptSlave_RotateAxis
|
|
(
|
|
"rotateaxis",
|
|
EV_SCRIPTONLY,
|
|
"if",
|
|
"axis avelocity",
|
|
"Rotate about the specified axis at the specified angular velocity."
|
|
);
|
|
Event EV_ScriptSlave_RotateDownTo
|
|
(
|
|
"rotatedownto",
|
|
EV_SCRIPTONLY,
|
|
"v",
|
|
"direction",
|
|
"Rotate down to the specified direction."
|
|
);
|
|
Event EV_ScriptSlave_RotateUpTo
|
|
(
|
|
"rotateupto",
|
|
EV_SCRIPTONLY,
|
|
"v",
|
|
"direction",
|
|
"Rotate up to the specified direction."
|
|
);
|
|
Event EV_ScriptSlave_RotateTo
|
|
(
|
|
"rotateto",
|
|
EV_SCRIPTONLY,
|
|
"v",
|
|
"direction",
|
|
"Rotate to the specified direction."
|
|
);
|
|
Event EV_ScriptSlave_OnTouch
|
|
(
|
|
"ontouch",
|
|
EV_SCRIPTONLY,
|
|
"s",
|
|
"label",
|
|
"Sets what label to jump to and process script at when touched."
|
|
);
|
|
Event EV_ScriptSlave_NoTouch
|
|
(
|
|
"notouch",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Removes the ontouch thread."
|
|
);
|
|
Event EV_ScriptSlave_OnUse
|
|
(
|
|
"onuse",
|
|
EV_SCRIPTONLY,
|
|
"s",
|
|
"label",
|
|
"Sets what label to jump to and process script at when used."
|
|
);
|
|
Event EV_ScriptSlave_NoUse
|
|
(
|
|
"nouse",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Removes the onuse thread."
|
|
);
|
|
Event EV_ScriptSlave_OnBlock
|
|
(
|
|
"onblock",
|
|
EV_SCRIPTONLY,
|
|
"s",
|
|
"label",
|
|
"Sets what label to jump to and process script at when blocked."
|
|
);
|
|
Event EV_ScriptSlave_NoBlock
|
|
(
|
|
"noblock",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Removes the onblock thread."
|
|
);
|
|
Event EV_ScriptSlave_OnTrigger
|
|
(
|
|
"ontrigger",
|
|
EV_SCRIPTONLY,
|
|
"s",
|
|
"label",
|
|
"Sets what label to jump to and process script at when triggered."
|
|
);
|
|
Event EV_ScriptSlave_NoTrigger
|
|
(
|
|
"notrigger",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Removes the ontrigger thread."
|
|
);
|
|
Event EV_ScriptSlave_OnDamage
|
|
(
|
|
"ondamage",
|
|
EV_SCRIPTONLY,
|
|
"s",
|
|
"label",
|
|
"Sets what label to jump to and process script at when damaged."
|
|
);
|
|
Event EV_ScriptSlave_NoDamage
|
|
(
|
|
"nodamage",
|
|
EV_DEFAULT,
|
|
NULL,
|
|
NULL,
|
|
"Removes the ondamage thread."
|
|
);
|
|
Event EV_ScriptSlave_SetMeansOfDeath
|
|
(
|
|
"setmeansofdeath",
|
|
EV_SCRIPTONLY,
|
|
"s",
|
|
"means_of_death",
|
|
"Set the damage means of death."
|
|
);
|
|
Event EV_ScriptSlave_SetDamageSpawn
|
|
(
|
|
"dmg",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"damage",
|
|
"Set the damage."
|
|
);
|
|
Event EV_ScriptSlave_FollowPath
|
|
(
|
|
"followpath",
|
|
EV_SCRIPTONLY,
|
|
"eSSSSSS",
|
|
"path arg1 arg2 arg3 arg4 arg5 arg6",
|
|
"Makes the script slave follow the specified path. The allowable arguments are ignoreangles,\n"
|
|
"normalangles, loop, and a number specifying the start time."
|
|
);
|
|
Event EV_ScriptSlave_EndPath
|
|
(
|
|
"endpath",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Stop following the path"
|
|
);
|
|
Event EV_ScriptSlave_MoveDone
|
|
(
|
|
"scriptslave_movedone",
|
|
EV_CODEONLY,
|
|
NULL,
|
|
NULL,
|
|
"Called when the script slave is doen moving"
|
|
);
|
|
Event EV_ScriptSlave_FollowingPath
|
|
(
|
|
"scriptslave_followingpath",
|
|
EV_CODEONLY,
|
|
NULL,
|
|
NULL,
|
|
"Called every frame to actually follow the path"
|
|
);
|
|
Event EV_ScriptSlave_Explode
|
|
(
|
|
"scriptSlave_explode",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"damage",
|
|
"Creates an explosion at the script slave's position"
|
|
);
|
|
Event EV_ScriptSlave_NotShootable
|
|
(
|
|
"notshootable",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Makes the script slave not shootable"
|
|
);
|
|
Event EV_ScriptSlave_OpenAreaPortal
|
|
(
|
|
"openportal",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Open the area portal enclosed in this object"
|
|
);
|
|
Event EV_ScriptSlave_CloseAreaPortal
|
|
(
|
|
"closeportal",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Close the area portal enclosed in this object"
|
|
);
|
|
Event EV_ScriptSlave_PhysicsOn
|
|
(
|
|
"physics_on",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Turn physics on this script object on"
|
|
);
|
|
Event EV_ScriptSlave_PhysicsOff
|
|
(
|
|
"physics_off",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Turn physics off this script object on"
|
|
);
|
|
Event EV_ScriptSlave_PhysicsVelocity
|
|
(
|
|
"physics_velocity",
|
|
EV_SCRIPTONLY,
|
|
"v",
|
|
"impulseVector",
|
|
"Add a physical impulse to an object when it is being physically simulated"
|
|
);
|
|
Event EV_ScriptSlave_StopEvent
|
|
(
|
|
"stopspline",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"stops an scriptobject from moving on a spline"
|
|
);
|
|
Event EV_ScriptSlave_ContinueEvent
|
|
(
|
|
"continuespline",
|
|
EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"makes a script object continue on a spline"
|
|
);
|
|
|
|
// 1ST PLAYABLE HACK
|
|
Event EV_ScriptSlave_Hack_SetTriggerParms
|
|
(
|
|
"setobjectparms",
|
|
EV_DEFAULT,
|
|
"ff",
|
|
"force_field_number trigger_number",
|
|
"HACK HACK HACK HACK HACK HACK HACK"
|
|
);
|
|
Event EV_ScriptSlave_Hack_GetForceFieldNumber
|
|
(
|
|
"getforcefieldnumber",
|
|
EV_DEFAULT,
|
|
"@f",
|
|
"number",
|
|
"HACK HACK HACK HACK HACK HACK HACK"
|
|
);
|
|
Event EV_ScriptSlave_Hack_GetTriggerNumber
|
|
(
|
|
"gettriggernumber",
|
|
EV_DEFAULT,
|
|
"@f",
|
|
"number",
|
|
"HACK HACK HACK HACK HACK HACK HACK"
|
|
);
|
|
Event EV_ScriptSlave_Hack_GetScanner
|
|
(
|
|
"getscanner",
|
|
EV_DEFAULT,
|
|
"@e",
|
|
"scanner",
|
|
"HACK HACK HACK HACK HACK HACK HACK"
|
|
);
|
|
|
|
Event EV_ScriptSlave_HandlesDamage
|
|
(
|
|
"handlesdamage",
|
|
EV_DEFAULT,
|
|
"b",
|
|
"damage_flag",
|
|
"sets the handlesdamage flag on the script slave"
|
|
);
|
|
Event EV_ScriptSlave_DamageEffect
|
|
(
|
|
"damageEffect",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"damageEffectModel",
|
|
"Sets the damage effect model name."
|
|
);
|
|
|
|
Event EV_ScriptSlave_BloodModel
|
|
(
|
|
"setBloodModel",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"bloodmodel",
|
|
"Sets the blood model"
|
|
);
|
|
|
|
Event EV_ScriptSlave_AddRequiredDamageMOD
|
|
(
|
|
"addrequireddamagemod",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"MOD_String",
|
|
"Adds the required MOD for damage to be applied"
|
|
);
|
|
|
|
Event EV_ScriptSlave_SetCanBeAttackedByOtherScriptObjects
|
|
(
|
|
"allowAttackFromOtherScriptObjects",
|
|
EV_DEFAULT,
|
|
"b",
|
|
"allow_flag",
|
|
"Sets the _canBeAttackedByOtherScriptSlaves variable"
|
|
);
|
|
|
|
CLASS_DECLARATION( Trigger, ScriptSlave, "script_object" )
|
|
{
|
|
{ &EV_Bind, &ScriptSlave::BindEvent },
|
|
{ &EV_Unbind, &ScriptSlave::EventUnbind },
|
|
{ &EV_ScriptSlave_DoMove, &ScriptSlave::DoMove },
|
|
{ &EV_ScriptSlave_NewOrders, &ScriptSlave::NewOrders },
|
|
{ &EV_ScriptSlave_Angles, &ScriptSlave::SetAnglesEvent },
|
|
{ &EV_SetAngle, &ScriptSlave::SetAngleEvent },
|
|
{ &EV_Model, &ScriptSlave::SetModelEvent },
|
|
{ &EV_ScriptSlave_Trigger, &ScriptSlave::TriggerEvent },
|
|
{ &EV_ScriptSlave_Next, &ScriptSlave::GotoNextWaypoint },
|
|
{ &EV_ScriptSlave_JumpTo, &ScriptSlave::JumpTo },
|
|
{ &EV_ScriptSlave_MoveTo, &ScriptSlave::MoveToEvent },
|
|
{ &EV_ScriptSlave_MoveToPosition, &ScriptSlave::MoveToPositionEvent },
|
|
{ &EV_ScriptSlave_Speed, &ScriptSlave::SetSpeed },
|
|
{ &EV_ScriptSlave_Time, &ScriptSlave::SetTime },
|
|
{ &EV_ScriptSlave_MoveUp, &ScriptSlave::MoveUp },
|
|
{ &EV_ScriptSlave_MoveDown, &ScriptSlave::MoveDown },
|
|
{ &EV_ScriptSlave_MoveNorth, &ScriptSlave::MoveNorth },
|
|
{ &EV_ScriptSlave_MoveSouth, &ScriptSlave::MoveSouth },
|
|
{ &EV_ScriptSlave_MoveEast, &ScriptSlave::MoveEast },
|
|
{ &EV_ScriptSlave_MoveWest, &ScriptSlave::MoveWest },
|
|
{ &EV_ScriptSlave_MoveForward, &ScriptSlave::MoveForward },
|
|
{ &EV_ScriptSlave_MoveBackward, &ScriptSlave::MoveBackward },
|
|
{ &EV_ScriptSlave_MoveLeft, &ScriptSlave::MoveLeft },
|
|
{ &EV_ScriptSlave_MoveRight, &ScriptSlave::MoveRight },
|
|
{ &EV_ScriptSlave_RotateXDownTo, &ScriptSlave::RotateXdownto },
|
|
{ &EV_ScriptSlave_RotateYDownTo, &ScriptSlave::RotateYdownto },
|
|
{ &EV_ScriptSlave_RotateZDownTo, &ScriptSlave::RotateZdownto },
|
|
{ &EV_ScriptSlave_RotateXUpTo, &ScriptSlave::RotateXupto },
|
|
{ &EV_ScriptSlave_RotateYUpTo, &ScriptSlave::RotateYupto },
|
|
{ &EV_ScriptSlave_RotateZUpTo, &ScriptSlave::RotateZupto },
|
|
{ &EV_ScriptSlave_RotateXDown, &ScriptSlave::RotateXdown },
|
|
{ &EV_ScriptSlave_RotateYDown, &ScriptSlave::RotateYdown },
|
|
{ &EV_ScriptSlave_RotateZDown, &ScriptSlave::RotateZdown },
|
|
{ &EV_ScriptSlave_RotateXUp, &ScriptSlave::RotateXup },
|
|
{ &EV_ScriptSlave_RotateYUp, &ScriptSlave::RotateYup },
|
|
{ &EV_ScriptSlave_RotateZUp, &ScriptSlave::RotateZup },
|
|
{ &EV_ScriptSlave_RotateX, &ScriptSlave::RotateX },
|
|
{ &EV_ScriptSlave_RotateY, &ScriptSlave::RotateY },
|
|
{ &EV_ScriptSlave_RotateZ, &ScriptSlave::RotateZ },
|
|
{ &EV_ScriptSlave_RotateAxisDownTo, &ScriptSlave::RotateAxisdownto },
|
|
{ &EV_ScriptSlave_RotateAxisUpTo, &ScriptSlave::RotateAxisupto },
|
|
{ &EV_ScriptSlave_RotateAxisDown, &ScriptSlave::RotateAxisdown },
|
|
{ &EV_ScriptSlave_RotateAxisUp, &ScriptSlave::RotateAxisup },
|
|
{ &EV_ScriptSlave_RotateAxis, &ScriptSlave::RotateZ },
|
|
{ &EV_ScriptSlave_OnTouch, &ScriptSlave::OnTouch },
|
|
{ &EV_ScriptSlave_NoTouch, &ScriptSlave::NoTouch },
|
|
{ &EV_ScriptSlave_OnUse, &ScriptSlave::OnUse },
|
|
{ &EV_ScriptSlave_NoUse, &ScriptSlave::NoUse },
|
|
{ &EV_ScriptSlave_OnBlock, &ScriptSlave::OnBlock },
|
|
{ &EV_ScriptSlave_NoBlock, &ScriptSlave::NoBlock },
|
|
{ &EV_ScriptSlave_OnTrigger, &ScriptSlave::OnTrigger },
|
|
{ &EV_ScriptSlave_NoTrigger, &ScriptSlave::NoTrigger },
|
|
{ &EV_ScriptSlave_OnDamage, &ScriptSlave::OnDamage },
|
|
{ &EV_ScriptSlave_NoDamage, &ScriptSlave::NoDamage },
|
|
{ &EV_ScriptSlave_SetMeansOfDeath, &ScriptSlave::SetMeansOfDeath },
|
|
{ &EV_ScriptSlave_SetDamageSpawn, &ScriptSlave::SetDamage },
|
|
{ &EV_ScriptSlave_FollowPath, &ScriptSlave::FollowPath },
|
|
{ &EV_ScriptSlave_EndPath, &ScriptSlave::EndPath },
|
|
{ &EV_ScriptSlave_FollowingPath, &ScriptSlave::FollowingPath },
|
|
{ &EV_Touch, &ScriptSlave::TouchFunc },
|
|
{ &EV_Blocked, &ScriptSlave::BlockFunc },
|
|
{ &EV_Activate, &ScriptSlave::TriggerFunc },
|
|
{ &EV_Use, &ScriptSlave::UseFunc },
|
|
{ &EV_ScriptSlave_MoveDone, &ScriptSlave::MoveEnd },
|
|
{ &EV_Damage, &ScriptSlave::DamageFunc },
|
|
{ &EV_ScriptSlave_RotateDownTo, &ScriptSlave::Rotatedownto },
|
|
{ &EV_ScriptSlave_RotateUpTo, &ScriptSlave::Rotateupto },
|
|
{ &EV_ScriptSlave_RotateTo, &ScriptSlave::Rotateto },
|
|
{ &EV_ScriptSlave_Explode, &ScriptSlave::Explode },
|
|
{ &EV_ScriptSlave_NotShootable, &ScriptSlave::NotShootable },
|
|
{ &EV_ScriptSlave_OpenAreaPortal, &ScriptSlave::OpenPortal },
|
|
{ &EV_ScriptSlave_CloseAreaPortal, &ScriptSlave::ClosePortal },
|
|
{ &EV_ScriptSlave_PhysicsOn, &ScriptSlave::PhysicsOn },
|
|
{ &EV_ScriptSlave_PhysicsOff, &ScriptSlave::PhysicsOff },
|
|
{ &EV_ScriptSlave_PhysicsVelocity, &ScriptSlave::PhysicsVelocity },
|
|
{ &EV_ScriptSlave_StopEvent, &ScriptSlave::StopEvent },
|
|
{ &EV_ScriptSlave_ContinueEvent, &ScriptSlave::ContinueEvent },
|
|
{ &EV_SetGameplayDamage, &ScriptSlave::setDamage },
|
|
{ &EV_ScriptSlave_HandlesDamage, &ScriptSlave::HandlesDamage },
|
|
{ &EV_ScriptSlave_DamageEffect, &ScriptSlave::setDamageEffect },
|
|
{ &EV_ScriptSlave_BloodModel, &ScriptSlave::setBloodModel },
|
|
{ &EV_ScriptSlave_AddRequiredDamageMOD, &ScriptSlave::addRequiredDamageMOD },
|
|
{ &EV_ScriptSlave_SetCanBeAttackedByOtherScriptObjects, &ScriptSlave::setCanBeAttackedByOtherSlaves },
|
|
|
|
//1ST PLAYABLE HACK STUFF
|
|
{ &EV_ScriptSlave_Hack_SetTriggerParms, &ScriptSlave::Hack_AddParms },
|
|
{ &EV_ScriptSlave_Hack_GetForceFieldNumber, &ScriptSlave::Hack_GetForceFieldNumber },
|
|
{ &EV_ScriptSlave_Hack_GetTriggerNumber, &ScriptSlave::Hack_GetTriggerNumber },
|
|
{ &EV_ScriptSlave_Hack_GetScanner, &ScriptSlave::Hack_GetScanner },
|
|
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
ScriptSlave::ScriptSlave()
|
|
{
|
|
mover = new Mover( this );
|
|
|
|
if ( LoadingSavegame )
|
|
{
|
|
// Archive function will setup all necessary data
|
|
return;
|
|
}
|
|
// this is a normal entity
|
|
edict->s.eType = ET_GENERAL;
|
|
|
|
speed = 100;
|
|
takedamage = DAMAGE_YES;
|
|
waypoint = NULL;
|
|
SetNewAngles( localangles );
|
|
SetNewPosition( GetLocalOrigin() );
|
|
traveltime = 0;
|
|
commandswaiting = false;
|
|
movethread = NULL;
|
|
touchthread = NULL;
|
|
blockthread = NULL;
|
|
damagethread = NULL;
|
|
triggerthread = NULL;
|
|
usethread = NULL;
|
|
splinePath = NULL;
|
|
splineangles = false;
|
|
attack_finished = 0;
|
|
thinking = true;
|
|
|
|
dmg = 2;
|
|
dmg_means_of_death = MOD_CRUSH;
|
|
|
|
setMoveType( MOVETYPE_PUSH );
|
|
setSolidType( SOLID_NOT );
|
|
|
|
//1ST PLAYABLE HACK
|
|
_forcefieldNumber = -1.0f;
|
|
_triggerNumber = -1.0f;
|
|
_scanner = NULL;
|
|
|
|
_portalOpen = false;
|
|
_handlesDamage = false;
|
|
|
|
_nextNeedToUseTime = 0.0f;
|
|
_canBeAttackedByOtherScriptSlaves = true;
|
|
|
|
if ( spawnflags & 1 )
|
|
{
|
|
PostEvent( EV_BecomeNonSolid, EV_POSTSPAWN );
|
|
}
|
|
}
|
|
|
|
ScriptSlave::~ScriptSlave()
|
|
{
|
|
if ( splinePath )
|
|
{
|
|
delete splinePath;
|
|
splinePath = NULL;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------
|
|
//
|
|
// Name: setDamage
|
|
// Class: ScriptSlave
|
|
//
|
|
// Description: This function acts as a filter to the real function.
|
|
// It gets data from the database, and then passes it
|
|
// along to the original event. This is here as an attempt
|
|
// to sway people into using the database standard instead of
|
|
// hardcoded numbers.
|
|
//
|
|
// Parameters: Event *ev
|
|
// str -- The value keyword from the database (low, medium, high, etc).
|
|
//
|
|
// Returns: None
|
|
//
|
|
//--------------------------------------------------------------
|
|
void ScriptSlave::setDamage( Event *ev )
|
|
{
|
|
if ( ev->NumArgs() < 1 )
|
|
return;
|
|
|
|
GameplayManager *gpm = GameplayManager::getTheGameplayManager();
|
|
if ( !gpm->hasFormula("OffensiveDamage") )
|
|
return;
|
|
|
|
str damagestr = ev->GetString( 1 );
|
|
float damagemod = 1.0f;
|
|
if ( gpm->getDefine(damagestr) != "" )
|
|
damagemod = (float)atof(gpm->getDefine(damagestr));
|
|
GameplayFormulaData fd(this, 0, 0, "");
|
|
float finaldamage = gpm->calculate("OffensiveDamage", fd, damagemod);
|
|
Event *newev = new Event(EV_ScriptSlave_SetDamageSpawn);
|
|
newev->AddFloat(finaldamage);
|
|
ProcessEvent(newev);
|
|
}
|
|
|
|
void ScriptSlave::setOrigin( const Vector &point )
|
|
{
|
|
Trigger::setOrigin( point );
|
|
SetNewPosition( GetLocalOrigin() );
|
|
}
|
|
|
|
void ScriptSlave::setOrigin( void )
|
|
{
|
|
Trigger::setOrigin();
|
|
SetNewPosition( GetLocalOrigin() );
|
|
}
|
|
|
|
void ScriptSlave::NewOrders( Event *ev )
|
|
{
|
|
// make sure position and angles are current
|
|
SetNewAngles( localangles );
|
|
SetNewPosition( GetLocalOrigin() );
|
|
}
|
|
|
|
void ScriptSlave::BindEvent( Event *ev )
|
|
{
|
|
Entity *ent;
|
|
|
|
ent = ev->GetEntity( 1 );
|
|
if ( ent )
|
|
{
|
|
bind( ent );
|
|
}
|
|
|
|
// make sure position and angles are current
|
|
SetNewAngles( localangles );
|
|
SetNewPosition( GetLocalOrigin() );
|
|
}
|
|
|
|
void ScriptSlave::EventUnbind( Event *ev )
|
|
{
|
|
unbind();
|
|
|
|
// make sure position and angles are current
|
|
SetNewAngles( localangles );
|
|
SetNewPosition( GetLocalOrigin() );
|
|
}
|
|
|
|
void ScriptSlave::DoMove( Event *ev )
|
|
{
|
|
float dist;
|
|
CThread *thread;
|
|
Event *event;
|
|
|
|
thread = ev->GetThread();
|
|
assert( thread );
|
|
if ( thread && thread->WaitingFor( this ) )
|
|
{
|
|
if ( movethread && ( movethread != thread ) )
|
|
{
|
|
// warn the user
|
|
ev->Error( "Overriding previous move commands for '%s'\n", TargetName() );
|
|
|
|
// Yeah, we're not REALLY done, but we tell our old thread
|
|
// that we are so that it doesn't wait forever
|
|
event = new Event( EV_MoveDone );
|
|
event->AddEntity( this );
|
|
movethread->ProcessEvent( event );
|
|
}
|
|
|
|
movethread = thread;
|
|
}
|
|
if ( commandswaiting )
|
|
{
|
|
if ( splinePath )
|
|
{
|
|
moving = true;
|
|
PostEvent( EV_ScriptSlave_FollowingPath, 0.0f );
|
|
}
|
|
else
|
|
{
|
|
float t = traveltime;
|
|
if ( t == 0.0f )
|
|
{
|
|
dist = Vector( GetNewPosition() - GetLocalOrigin() ).length();
|
|
t = dist / speed;
|
|
}
|
|
moving = true;
|
|
mover->LinearInterpolate( GetNewPosition(), GetNewAngles(), t, EV_ScriptSlave_MoveDone );
|
|
}
|
|
commandswaiting = false;
|
|
}
|
|
else if ( movethread && ( movethread == thread ) && !moving )
|
|
{
|
|
// No commands, so tell the master that we're done
|
|
PostEvent( EV_ScriptSlave_MoveDone, 0.0f );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void ScriptSlave::MoveEnd( Event *ev )
|
|
{
|
|
Event *event;
|
|
|
|
moving = false;
|
|
commandswaiting = false;
|
|
SetNewAngles( localangles );
|
|
SetNewPosition( GetLocalOrigin() );
|
|
|
|
if ( movethread )
|
|
{
|
|
event = new Event( EV_MoveDone );
|
|
event->AddEntity( this );
|
|
movethread->ProcessEvent( event );
|
|
movethread = NULL;
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::SetAnglesEvent( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
setAngles( ev->GetVector( 1 ) );
|
|
SetNewAngles( localangles );
|
|
}
|
|
|
|
void ScriptSlave::SetAngleEvent( Event *ev )
|
|
{
|
|
float angle;
|
|
|
|
angle = ev->GetFloat( 1 );
|
|
if ( angle == -1.0f )
|
|
{
|
|
ForwardDir = Vector( 0.0f, 0.0f, 90.0f );
|
|
}
|
|
else if ( angle == -2.0f )
|
|
{
|
|
ForwardDir = Vector( 0.0f, 0.0f, -90.0f );
|
|
}
|
|
else
|
|
{
|
|
ForwardDir = Vector( 0.0f, angle, 0.0f );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::SetModelEvent( Event *ev )
|
|
{
|
|
const char *m;
|
|
|
|
m = ev->GetString( 1 );
|
|
|
|
setModel( m );
|
|
showModel();
|
|
|
|
if ( !edict->s.modelindex )
|
|
{
|
|
hideModel();
|
|
setSolidType( SOLID_NOT );
|
|
}
|
|
else if ( !m || strstr( m, ".tik" ) )
|
|
{
|
|
setSolidType( SOLID_BBOX );
|
|
}
|
|
else if ( strstr( m, ".spr" ) )
|
|
{
|
|
setSolidType( SOLID_NOT );
|
|
}
|
|
else
|
|
{
|
|
setSolidType( SOLID_BSP );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::TriggerEvent( Event *ev )
|
|
{
|
|
Entity *ent;
|
|
Event *e;
|
|
str name;
|
|
|
|
name = ev->GetString(1);
|
|
ent = G_FindTarget(NULL, name);
|
|
|
|
if ( ent )
|
|
{
|
|
SetTarget( ent->TargetName() );
|
|
|
|
e = new Event( EV_Trigger_ActivateTargets );
|
|
//fixme
|
|
//get "other"
|
|
e->AddEntity( world );
|
|
ProcessEvent( e );
|
|
}
|
|
else
|
|
{
|
|
gi.WDPrintf( "Invalid entity reference '%s'.\n", name.c_str() );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::GotoNextWaypoint( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
|
|
if ( !waypoint )
|
|
{
|
|
ev->Error( "%s is currently not at a waypoint", TargetName() );
|
|
return;
|
|
}
|
|
|
|
waypoint = ( Waypoint * )G_FindTarget( NULL, waypoint->Target() );
|
|
if ( !waypoint )
|
|
{
|
|
ev->Error( "%s could not find waypoint %s", TargetName(), waypoint->Target() );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
SetNewPosition( waypoint->origin );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::JumpTo( Event *ev )
|
|
{
|
|
Entity *part;
|
|
|
|
//
|
|
// see if it is a vector
|
|
//
|
|
if ( ev->IsVectorAt( 1 ) )
|
|
{
|
|
SetNewPosition( ev->GetVector( 1 ) );
|
|
if ( bind_info && bind_info->bindmaster )
|
|
{
|
|
SetLocalOrigin( bind_info->bindmaster->getLocalVector( GetNewPosition() - bind_info->bindmaster->origin ) );
|
|
}
|
|
else
|
|
{
|
|
SetLocalOrigin( GetNewPosition() );
|
|
}
|
|
|
|
part = this;
|
|
|
|
while( part )
|
|
{
|
|
part->setOrigin();
|
|
part->origin.copyTo( part->edict->s.origin2 );
|
|
part->edict->s.renderfx |= RF_FRAMELERP;
|
|
|
|
if ( part->bind_info )
|
|
part = part->bind_info->teamchain;
|
|
else
|
|
part = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
waypoint = ( Waypoint * )ev->GetEntity( 1 );
|
|
if ( waypoint )
|
|
{
|
|
SetNewPosition( waypoint->GetLocalOrigin() );
|
|
if ( bind_info && bind_info->bindmaster )
|
|
{
|
|
SetLocalOrigin( bind_info->bindmaster->getLocalVector( GetNewPosition() - bind_info->bindmaster->origin ) );
|
|
}
|
|
else
|
|
{
|
|
SetLocalOrigin( GetNewPosition() );
|
|
}
|
|
|
|
part = this;
|
|
|
|
while( part )
|
|
{
|
|
part->setOrigin();
|
|
part->origin.copyTo( part->edict->s.origin2 );
|
|
part->edict->s.renderfx |= RF_FRAMELERP;
|
|
|
|
if ( part->bind_info )
|
|
part = part->bind_info->teamchain;
|
|
else
|
|
part = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::MoveToEvent( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
|
|
waypoint = ( Waypoint * )ev->GetEntity( 1 );
|
|
|
|
if ( waypoint )
|
|
{
|
|
SetNewPosition( waypoint->origin );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::MoveToPositionEvent( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
|
|
SetNewPosition( ev->GetVector( 1 ) );
|
|
}
|
|
|
|
void ScriptSlave::SetSpeed( Event *ev )
|
|
{
|
|
speed = ev->GetFloat( 1 );
|
|
traveltime = 0;
|
|
}
|
|
|
|
void ScriptSlave::SetTime( Event *ev )
|
|
{
|
|
traveltime = ev->GetFloat( 1 );
|
|
}
|
|
|
|
// Relative move commands
|
|
|
|
void ScriptSlave::MoveUp( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
SetNewPosition( Vector( GetNewPosition().x, GetNewPosition().y, GetNewPosition().z + ev->GetFloat( 1 ) ) );
|
|
}
|
|
|
|
void ScriptSlave::MoveDown( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
SetNewPosition( Vector( GetNewPosition().x, GetNewPosition().y, GetNewPosition().z - ev->GetFloat( 1 ) ) );
|
|
}
|
|
|
|
void ScriptSlave::MoveNorth( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
SetNewPosition( Vector( GetNewPosition().x, GetNewPosition().y + ev->GetFloat( 1 ), GetNewPosition().z ) );
|
|
}
|
|
|
|
void ScriptSlave::MoveSouth( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
SetNewPosition( Vector( GetNewPosition().x, GetNewPosition().y - ev->GetFloat( 1 ), GetNewPosition().z ) );
|
|
}
|
|
|
|
void ScriptSlave::MoveEast( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
SetNewPosition( Vector( GetNewPosition().x + ev->GetFloat( 1 ), GetNewPosition().y, GetNewPosition().z ) );
|
|
}
|
|
|
|
void ScriptSlave::MoveWest( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
SetNewPosition( Vector( GetNewPosition().x - ev->GetFloat( 1 ), GetNewPosition().y, GetNewPosition().z ) );
|
|
}
|
|
|
|
void ScriptSlave::MoveForward( Event *ev )
|
|
{
|
|
Vector v;
|
|
Vector t;
|
|
|
|
commandswaiting = true;
|
|
|
|
t = GetNewAngles() + ForwardDir;
|
|
t.AngleVectors( &v, NULL, NULL );
|
|
|
|
SetNewPosition( GetNewPosition() + v * ev->GetFloat( 1 ) );
|
|
}
|
|
|
|
void ScriptSlave::MoveBackward( Event *ev )
|
|
{
|
|
Vector v;
|
|
Vector t;
|
|
|
|
commandswaiting = true;
|
|
|
|
t = GetNewAngles() + ForwardDir;
|
|
t.AngleVectors( &v, NULL, NULL );
|
|
|
|
SetNewPosition( GetNewPosition() - v * ev->GetFloat( 1 ) );
|
|
}
|
|
|
|
void ScriptSlave::MoveLeft( Event *ev )
|
|
{
|
|
Vector v;
|
|
Vector t;
|
|
|
|
commandswaiting = true;
|
|
|
|
t = GetNewAngles() + ForwardDir;
|
|
t.AngleVectors( NULL, &v, NULL );
|
|
|
|
SetNewPosition( GetNewPosition() + v * ev->GetFloat( 1 ) );
|
|
}
|
|
|
|
void ScriptSlave::MoveRight( Event *ev )
|
|
{
|
|
Vector t;
|
|
Vector v;
|
|
|
|
commandswaiting = true;
|
|
|
|
t = GetNewAngles() + ForwardDir;
|
|
t.AngleVectors( NULL, &v, NULL );
|
|
|
|
SetNewPosition( GetNewPosition() - v * ev->GetFloat( 1 ) );
|
|
}
|
|
|
|
// exact rotate commands
|
|
|
|
void ScriptSlave::RotateXdownto( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 0 ] = ev->GetFloat( 1 );
|
|
if ( newAngles[ 0 ] < localangles[ 0 ] )
|
|
{
|
|
newAngles[ 0 ] -= 360.0f;
|
|
}
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateYdownto( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 1 ] = ev->GetFloat( 1 );
|
|
if ( newAngles[ 1 ] < localangles[ 1 ] )
|
|
{
|
|
newAngles[ 1 ] -= 360.0f;
|
|
}
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateZdownto( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 2 ] = ev->GetFloat( 1 );
|
|
if ( newAngles[ 2 ] < localangles[ 2 ] )
|
|
{
|
|
newAngles[ 2 ] -= 360.0f;
|
|
}
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateAxisdownto( Event *ev )
|
|
{
|
|
int axis;
|
|
commandswaiting = true;
|
|
|
|
axis = ev->GetInteger( 1 );
|
|
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ axis ] = ev->GetFloat( 1 );
|
|
if ( newAngles[ axis ] < localangles[ axis ] )
|
|
{
|
|
newAngles[ axis ] -= 360.0f;
|
|
}
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateXupto( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 0 ] = ev->GetFloat( 1 );
|
|
if ( newAngles[ 0 ] < localangles[ 0 ] )
|
|
{
|
|
newAngles[ 0 ] += 360.0f;
|
|
}
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateYupto( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 1 ] = ev->GetFloat( 1 );
|
|
if ( newAngles[ 1 ] < localangles[ 1 ] )
|
|
{
|
|
newAngles[ 1 ] += 360.0f;
|
|
}
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateZupto( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 2 ] = ev->GetFloat( 1 );
|
|
if ( newAngles[ 2 ] < localangles[ 2 ] )
|
|
{
|
|
newAngles[ 2 ] += 360.0f;
|
|
}
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateAxisupto( Event *ev )
|
|
{
|
|
int axis;
|
|
commandswaiting = true;
|
|
|
|
axis = ev->GetInteger( 1 );
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ axis ] = ev->GetFloat( 1 );
|
|
if ( newAngles[ axis ] < localangles[ axis ] )
|
|
{
|
|
newAngles[ axis ] += 360.0f;
|
|
}
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
// full vector rotation
|
|
|
|
void ScriptSlave::Rotatedownto( Event *ev )
|
|
{
|
|
Vector ang;
|
|
commandswaiting = true;
|
|
|
|
ang = ev->GetVector( 1 );
|
|
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 0 ] = ang[ 0 ];
|
|
if ( newAngles[ 0 ] > localangles[ 0 ] )
|
|
{
|
|
newAngles[ 0 ] -= 360.0f;
|
|
}
|
|
newAngles[ 1 ] = ang[ 1 ];
|
|
if ( newAngles[ 1 ] > localangles[ 1 ] )
|
|
{
|
|
newAngles[ 1 ] -= 360.0f;
|
|
}
|
|
newAngles[ 2 ] = ang[ 2 ];
|
|
if ( newAngles[ 2 ] > localangles[ 2 ] )
|
|
{
|
|
newAngles[ 2 ] -= 360.0f;
|
|
}
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::Rotateupto( Event *ev )
|
|
{
|
|
Vector ang;
|
|
commandswaiting = true;
|
|
|
|
ang = ev->GetVector( 1 );
|
|
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 0 ] = ang[ 0 ];
|
|
if ( newAngles[ 0 ] < localangles[ 0 ] )
|
|
{
|
|
newAngles[ 0 ] += 360.0f;
|
|
}
|
|
newAngles[ 1 ] = ang[ 1 ];
|
|
if ( newAngles[ 1 ] < localangles[ 1 ] )
|
|
{
|
|
newAngles[ 1 ] += 360.0f;
|
|
}
|
|
newAngles[ 2 ] = ang[ 2 ];
|
|
if ( newAngles[ 2 ] < localangles[ 2 ] )
|
|
{
|
|
newAngles[ 2 ] += 360.0f;
|
|
}
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::Rotateto( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
|
|
Vector ang = ev->GetVector( 1 );
|
|
|
|
SetNewAngles( ang );
|
|
}
|
|
|
|
// Relative rotate commands
|
|
|
|
void ScriptSlave::RotateXdown( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 0 ] = localangles[ 0 ] - ev->GetFloat( 1 );
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateYdown( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 1 ] = localangles[ 1 ] - ev->GetFloat( 1 );
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateZdown( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 2 ] = localangles[ 2 ] - ev->GetFloat( 1 );
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateAxisdown( Event *ev )
|
|
{
|
|
int axis;
|
|
commandswaiting = true;
|
|
|
|
axis = ev->GetInteger( 1 );
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ axis ] = localangles[ axis ] - ev->GetFloat( 1 );
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateXup( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 0 ] = localangles[ 0 ] + ev->GetFloat( 1 );
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateYup( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 1 ] = localangles[ 1 ] + ev->GetFloat( 1 );
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateZup( Event *ev )
|
|
{
|
|
commandswaiting = true;
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ 2 ] = localangles[ 2 ] + ev->GetFloat( 1 );
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateAxisup( Event *ev )
|
|
{
|
|
int axis;
|
|
commandswaiting = true;
|
|
|
|
axis = ev->GetInteger( 1 );
|
|
Vector newAngles( GetNewAngles() );
|
|
newAngles[ axis ] = localangles[ axis ] + ev->GetFloat( 1 );
|
|
SetNewAngles( newAngles );
|
|
}
|
|
|
|
void ScriptSlave::RotateX( Event *ev )
|
|
{
|
|
avelocity[ 0 ] = ev->GetFloat( 1 );
|
|
}
|
|
|
|
void ScriptSlave::RotateY( Event *ev )
|
|
{
|
|
avelocity[ 1 ] = ev->GetFloat( 1 );
|
|
}
|
|
|
|
void ScriptSlave::RotateZ( Event *ev )
|
|
{
|
|
avelocity[ 2 ] = ev->GetFloat( 1 );
|
|
}
|
|
|
|
void ScriptSlave::RotateAxis( Event *ev )
|
|
{
|
|
int axis;
|
|
|
|
axis = ev->GetInteger( 1 );
|
|
avelocity[ axis ] = ev->GetFloat( 2 );
|
|
}
|
|
|
|
|
|
void ScriptSlave::OnTouch( Event *ev )
|
|
{
|
|
const char *jumpto;
|
|
|
|
touchlabel = "";
|
|
|
|
jumpto = ev->GetString( 1 );
|
|
touchthread = ev->GetThread();
|
|
|
|
assert( jumpto && touchthread );
|
|
if ( touchthread && !touchthread->labelExists( jumpto ) )
|
|
{
|
|
ev->Error( "Label '%s' not found", jumpto );
|
|
return;
|
|
}
|
|
|
|
// if it isn't solid than we need to change it to a trigger
|
|
if ( getSolidType() == SOLID_NOT )
|
|
{
|
|
setSolidType( SOLID_TRIGGER );
|
|
}
|
|
|
|
touchlabel = jumpto;
|
|
}
|
|
|
|
void ScriptSlave::NoTouch( Event *ev )
|
|
{
|
|
touchlabel = "";
|
|
// if it is a trigger than it wasn't solid, so restore that condition
|
|
if ( getSolidType() == SOLID_TRIGGER )
|
|
{
|
|
setSolidType( SOLID_NOT );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::TouchFunc( Event *ev )
|
|
{
|
|
Event *e;
|
|
Entity *other;
|
|
|
|
if ( touchlabel.length() )
|
|
{
|
|
// since we use a SafePtr, the thread pointer will be NULL if the thread has ended
|
|
// so we should just clear our label and continue
|
|
if ( !touchthread )
|
|
{
|
|
touchlabel = "";
|
|
return;
|
|
}
|
|
|
|
other = ev->GetEntity( 1 );
|
|
|
|
setActivatingEntity( other );
|
|
|
|
e = new Event( EV_ScriptThread_Callback );
|
|
e->AddEntity( this );
|
|
e->AddString( touchlabel );
|
|
e->AddEntity( other );
|
|
touchthread->ProcessEvent( e );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::OnBlock( Event *ev )
|
|
{
|
|
const char *jumpto;
|
|
|
|
blocklabel = "";
|
|
|
|
jumpto = ev->GetString( 1 );
|
|
blockthread = ev->GetThread();
|
|
|
|
assert( jumpto && blockthread );
|
|
if ( blockthread && !blockthread->labelExists( jumpto ) )
|
|
{
|
|
ev->Error( "Label '%s' not found", jumpto );
|
|
return;
|
|
}
|
|
|
|
blocklabel = jumpto;
|
|
}
|
|
|
|
void ScriptSlave::NoBlock( Event *ev )
|
|
{
|
|
blocklabel = "";
|
|
}
|
|
|
|
void ScriptSlave::BlockFunc( Event *ev )
|
|
{
|
|
Event *e;
|
|
Entity *other;
|
|
|
|
other = ev->GetEntity( 1 );
|
|
if ( level.time >= attack_finished )
|
|
{
|
|
attack_finished = level.time + ( float )0.5;
|
|
if ( dmg != 0 )
|
|
{
|
|
other->Damage( this, this, dmg, origin, vec_zero, vec_zero, 0, 0, dmg_means_of_death );
|
|
}
|
|
}
|
|
|
|
if ( blocklabel.length() )
|
|
{
|
|
// since we use a SafePtr, the thread pointer will be NULL if the thread has ended
|
|
// so we should just clear our label and continue
|
|
if ( !blockthread )
|
|
{
|
|
blocklabel = "";
|
|
return;
|
|
}
|
|
|
|
setActivatingEntity( other );
|
|
|
|
e = new Event( EV_ScriptThread_Callback );
|
|
e->AddEntity( this );
|
|
e->AddString( blocklabel );
|
|
e->AddEntity( other );
|
|
blockthread->ProcessEvent( e );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::OnTrigger( Event *ev )
|
|
{
|
|
const char *jumpto;
|
|
|
|
triggerlabel = "";
|
|
|
|
jumpto = ev->GetString( 1 );
|
|
triggerthread = ev->GetThread();
|
|
|
|
assert( jumpto && triggerthread );
|
|
|
|
if ( triggerthread && !triggerthread->labelExists( jumpto ) )
|
|
{
|
|
ev->Error( "Label '%s' not found", jumpto );
|
|
return;
|
|
}
|
|
|
|
triggerlabel = jumpto;
|
|
}
|
|
|
|
void ScriptSlave::NoTrigger( Event *ev )
|
|
{
|
|
triggerlabel = "";
|
|
}
|
|
|
|
void ScriptSlave::TriggerFunc( Event *ev )
|
|
{
|
|
Event *e;
|
|
Entity *other;
|
|
|
|
if ( triggerlabel.length() )
|
|
{
|
|
// since we use a SafePtr, the thread pointer will be NULL if the thread has ended
|
|
// so we should just clear our label and continue
|
|
if ( !triggerthread )
|
|
{
|
|
triggerlabel = "";
|
|
return;
|
|
}
|
|
|
|
other = ev->GetEntity( 1 );
|
|
|
|
setActivatingEntity( other );
|
|
|
|
e = new Event( EV_ScriptThread_Callback );
|
|
e->AddEntity( this );
|
|
e->AddString( triggerlabel );
|
|
e->AddEntity( other );
|
|
|
|
triggerthread->ProcessEvent( e );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::OnUse( Event *ev )
|
|
{
|
|
const char *jumpto;
|
|
|
|
uselabel = "";
|
|
|
|
jumpto = ev->GetString( 1 );
|
|
usethread = ev->GetThread();
|
|
|
|
assert( jumpto && usethread );
|
|
|
|
if ( usethread && !usethread->labelExists( jumpto ) )
|
|
{
|
|
ev->Error( "Label '%s' not found", jumpto );
|
|
return;
|
|
}
|
|
|
|
uselabel = jumpto;
|
|
}
|
|
|
|
void ScriptSlave::NoUse( Event *ev )
|
|
{
|
|
uselabel = "";
|
|
}
|
|
|
|
void ScriptSlave::UseFunc( Event *ev )
|
|
{
|
|
Event *e;
|
|
Entity *other;
|
|
|
|
other = ev->GetEntity( 1 );
|
|
|
|
// See if object == key
|
|
|
|
if ( other->isSubclassOf( Equipment ) )
|
|
{
|
|
Equipment *equipment = (Equipment *)other;
|
|
|
|
if ( equipment->getTypeName() != key )
|
|
return;
|
|
}
|
|
else if ( key.length() )
|
|
{
|
|
if ( !other->isSubclassOf( Sentient ) || !( ( (Sentient *)other )->HasItem( key.c_str() ) ) )
|
|
{
|
|
Item *item;
|
|
ClassDef *cls;
|
|
|
|
cls = getClass( key.c_str() );
|
|
if ( !cls )
|
|
{
|
|
gi.WDPrintf( "No item named '%s'\n", key.c_str() );
|
|
return;
|
|
}
|
|
item = ( Item * )cls->newInstance();
|
|
item->CancelEventsOfType( EV_Item_DropToFloor );
|
|
item->CancelEventsOfType( EV_Remove );
|
|
item->ProcessPendingEvents();
|
|
gi.centerprintf ( other->edict, CENTERPRINT_IMPORTANCE_NORMAL, "$$ItemNeeded$$%s", item->getName().c_str() );
|
|
delete item;
|
|
return;
|
|
}
|
|
else if ( other->isSubclassOf( Sentient ) )
|
|
{
|
|
Item *item = ( (Sentient *)other )->FindItem( key.c_str() );
|
|
|
|
if ( !item )
|
|
return;
|
|
|
|
if ( item->isSubclassOf( Equipment ) )
|
|
{
|
|
if ( _nextNeedToUseTime < level.time )
|
|
{
|
|
gi.centerprintf ( other->edict, CENTERPRINT_IMPORTANCE_NORMAL, "$$NeedToUse$$ %s", key.c_str() );
|
|
|
|
if ( other->isSubclassOf( Player ) )
|
|
{
|
|
Player *player = (Player *)other;
|
|
|
|
player->loadUseItem( key );
|
|
}
|
|
|
|
_nextNeedToUseTime = level.time + 1.0f;
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( uselabel.length() )
|
|
{
|
|
//ScriptVariableList *vars;
|
|
|
|
// since we use a SafePtr, the thread pointer will be NULL if the thread has ended
|
|
// so we should just clear our label and continue
|
|
if ( !usethread )
|
|
{
|
|
uselabel = "";
|
|
return;
|
|
}
|
|
|
|
setActivatingEntity( other );
|
|
|
|
e = new Event( EV_ScriptThread_Callback );
|
|
e->AddEntity( this );
|
|
e->AddString( uselabel );
|
|
e->AddEntity( other );
|
|
|
|
/* vars = usethread->Vars();
|
|
vars->SetVariable( "other", other );
|
|
if ( key.length() )
|
|
{
|
|
vars->SetVariable( "key", key.c_str() );
|
|
} */
|
|
usethread->ProcessEvent( e );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::OnDamage( Event *ev )
|
|
{
|
|
const char *jumpto;
|
|
|
|
damagelabel = "";
|
|
|
|
jumpto = ev->GetString( 1 );
|
|
damagethread = ev->GetThread();
|
|
|
|
assert( jumpto && damagethread );
|
|
|
|
if ( damagethread && !damagethread->labelExists( jumpto ) )
|
|
{
|
|
ev->Error( "Label '%s' not found", jumpto );
|
|
return;
|
|
}
|
|
|
|
damagelabel = jumpto;
|
|
}
|
|
|
|
void ScriptSlave::NoDamage( Event *ev )
|
|
{
|
|
damagelabel = "";
|
|
}
|
|
|
|
void ScriptSlave::DamageFunc( Event *ev )
|
|
{
|
|
Event *e;
|
|
//Entity *inflictor;
|
|
Entity *attacker;
|
|
//int damage;
|
|
//Vector position;
|
|
//Vector direction;
|
|
//ScriptVariableList *vars;
|
|
|
|
attacker = ev->GetEntity( 3 );
|
|
|
|
if ( !_canBeAttackedByOtherScriptSlaves )
|
|
{
|
|
if ( attacker->isSubclassOf(ScriptSlave) )
|
|
return;
|
|
}
|
|
|
|
if ( _handlesDamage )
|
|
{
|
|
Event *newDamageEvent = new Event (ev);
|
|
Entity::DamageEvent(newDamageEvent);
|
|
}
|
|
|
|
if ( damagelabel.length() )
|
|
{
|
|
// since we use a SafePtr, the thread pointer will be NULL if the thread has ended
|
|
// so we should just clear our label and continue
|
|
if ( !damagethread )
|
|
{
|
|
damagelabel = "";
|
|
return;
|
|
}
|
|
|
|
if( _requiredMODlist.NumObjects() != 0 )
|
|
{
|
|
bool modMatches = false;
|
|
for( int i = 1; !modMatches && i <= _requiredMODlist.NumObjects(); i++ )
|
|
{
|
|
str& modname = _requiredMODlist.ObjectAt( i );
|
|
int modID = MOD_NameToNum( modname );
|
|
int damageMOD = ev->GetInteger( 9 );
|
|
|
|
if ( modID == damageMOD )
|
|
modMatches = true;
|
|
}
|
|
|
|
if( !modMatches )
|
|
return;
|
|
}
|
|
|
|
|
|
setActivatingEntity( attacker );
|
|
|
|
e = new Event( EV_ScriptThread_Callback );
|
|
e->AddEntity( this );
|
|
e->AddString( damagelabel );
|
|
e->AddEntity( attacker );
|
|
|
|
/* damage = ev->GetInteger( 1 );
|
|
inflictor = ev->GetEntity( 2 );
|
|
position = ev->GetVector( 4 );
|
|
direction = ev->GetVector( 5 ); */
|
|
|
|
/* vars = damagethread->Vars();
|
|
vars->SetVariable( "damage", damage );
|
|
vars->SetVariable( "inflictor", inflictor );
|
|
vars->SetVariable( "attacker", attacker );
|
|
vars->SetVariable( "position", position );
|
|
vars->SetVariable( "direction", direction ); */
|
|
damagethread->ProcessEvent( e );
|
|
}
|
|
|
|
if ( _bloodModel.length() )
|
|
{
|
|
SpawnEffect( _bloodModel , ev->GetVector( 4 ) , ev->GetVector( 6 ) , 1.0f );
|
|
}
|
|
|
|
if ( _damageEffect.length() )
|
|
{
|
|
//SpawnEffect( "models/fx/fx-impactburn-sniperrifle.tik", ev->GetVector( 4 ), ev->GetVector( 6 ), 1.0f );
|
|
SpawnEffect( "models/fx/fx-electricitymesh-impactpoint.tik", ev->GetVector( 4 ), ev->GetVector( 6 ), 1.0f );
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::SetDamage( Event *ev )
|
|
{
|
|
dmg = ev->GetFloat( 1 );
|
|
}
|
|
|
|
void ScriptSlave::SetMeansOfDeath( Event *ev )
|
|
{
|
|
dmg_means_of_death = MOD_NameToNum( ev->GetString( 1 ) );
|
|
}
|
|
|
|
void ScriptSlave::CreatePath( SplinePath *path, splinetype_t type )
|
|
{
|
|
SplinePath* node;
|
|
SplinePath* nextNode;
|
|
|
|
if ( !splinePath )
|
|
{
|
|
splinePath = new BSpline;
|
|
}
|
|
|
|
splinePath->Clear();
|
|
splinePath->SetType( type );
|
|
|
|
node = path;
|
|
while( node != NULL )
|
|
{
|
|
splinePath->AppendControlPoint( node->origin, node->angles, node->speed );
|
|
|
|
// get the next node and check it before using it
|
|
nextNode = node->GetNext();
|
|
if( nextNode == node )
|
|
{
|
|
gi.Error( ERR_DROP, "info_splinepath '%s' targets itself\n", node->targetname.c_str() );
|
|
}
|
|
|
|
// don't loop
|
|
if ( nextNode == path )
|
|
{
|
|
break;
|
|
}
|
|
|
|
// move to the next node
|
|
node = nextNode;
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::FollowPath( Event *ev )
|
|
{
|
|
int i, argnum;
|
|
Entity * ent;
|
|
const char * token;
|
|
SplinePath *path;
|
|
qboolean clamp;
|
|
float starttime;
|
|
|
|
|
|
ent = ev->GetEntity( 1 );
|
|
argnum = 2;
|
|
starttime = -2;
|
|
clamp = true;
|
|
ignoreangles = false;
|
|
splineangles = true;
|
|
for ( i = argnum; i <= ev->NumArgs() ; i++ )
|
|
{
|
|
token = ev->GetString( i );
|
|
if (!strcmpi( token, "ignoreangles"))
|
|
{
|
|
ignoreangles = true;
|
|
}
|
|
else if (!strcmpi( token, "normalangles"))
|
|
{
|
|
splineangles = false;
|
|
}
|
|
else if (!strcmpi (token, "loop"))
|
|
{
|
|
clamp = false;
|
|
}
|
|
else if ( IsNumeric( token ) )
|
|
{
|
|
starttime = (float)atof( token );
|
|
}
|
|
else
|
|
{
|
|
ev->Error( "Unknown followpath command %s.", token );
|
|
}
|
|
}
|
|
if ( ent && ent->isSubclassOf( SplinePath ) )
|
|
{
|
|
commandswaiting = true;
|
|
path = ( SplinePath * )ent;
|
|
if ( clamp )
|
|
CreatePath( path, SPLINE_CLAMP );
|
|
else
|
|
CreatePath( path, SPLINE_LOOP );
|
|
|
|
currentNode = path;
|
|
|
|
if ( currentNode->thread != "" )
|
|
{
|
|
if ( !ExecuteThread( currentNode->thread , true , this) )
|
|
{
|
|
gi.Error( ERR_DROP, "Scriptslave could not start thread '%s' from info_splinepath '%s'\n",
|
|
currentNode->thread.c_str(), currentNode->targetname.c_str() );
|
|
}
|
|
}
|
|
|
|
if ( currentNode->triggertarget != "" )
|
|
{
|
|
Entity *ent;
|
|
Event *event;
|
|
|
|
ent = NULL;
|
|
do
|
|
{
|
|
ent = G_FindTarget( ent, currentNode->triggertarget.c_str() );
|
|
if ( !ent )
|
|
{
|
|
break;
|
|
}
|
|
event = new Event( EV_Activate );
|
|
event->AddEntity( this );
|
|
ent->PostEvent( event, 0.0f );
|
|
}
|
|
while ( 1 );
|
|
}
|
|
|
|
splineTime = starttime;
|
|
lastTime = (int)(splineTime + 2.0f);
|
|
newTime = (int)(splineTime + 2.0f);
|
|
CancelEventsOfType( EV_ScriptSlave_FollowingPath );
|
|
if ( !ignoreangles )
|
|
{
|
|
avelocity = vec_zero;
|
|
}
|
|
velocity = vec_zero;
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::EndPath( Event *ev )
|
|
{
|
|
if ( !splinePath )
|
|
return;
|
|
|
|
delete splinePath;
|
|
splinePath = NULL;
|
|
velocity = vec_zero;
|
|
if ( !ignoreangles )
|
|
{
|
|
avelocity = vec_zero;
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::FollowingPath( Event *ev )
|
|
{
|
|
Vector pos;
|
|
Vector orient;
|
|
float speed_multiplier;
|
|
|
|
if ( !splinePath )
|
|
return;
|
|
|
|
if ( !thinking )
|
|
{
|
|
velocity = vec_zero;
|
|
if ( !ignoreangles )
|
|
{
|
|
avelocity = vec_zero;
|
|
}
|
|
|
|
return;
|
|
//PostEvent( EV_ScriptSlave_FollowingPath, level.frametime );
|
|
}
|
|
|
|
if ( ( splinePath->GetType() == SPLINE_CLAMP ) && ( splineTime > ( splinePath->EndPoint() - 2.0f ) ) )
|
|
{
|
|
delete splinePath;
|
|
splinePath = NULL;
|
|
velocity = vec_zero;
|
|
if ( !ignoreangles )
|
|
{
|
|
avelocity = vec_zero;
|
|
}
|
|
moving = false;
|
|
ProcessEvent( EV_ScriptSlave_MoveDone );
|
|
return;
|
|
}
|
|
|
|
if ( ( lastTime != newTime ) && currentNode )
|
|
{
|
|
if ( newTime > 1 )
|
|
{
|
|
|
|
if ( currentNode->thread != "" )
|
|
{
|
|
if ( !ExecuteThread( currentNode->thread ,true , this) )
|
|
{
|
|
gi.Error( ERR_DROP, "Scriptslave could not start thread '%s' from info_splinepath '%s'\n",
|
|
currentNode->thread.c_str(), currentNode->targetname.c_str() );
|
|
}
|
|
}
|
|
|
|
if ( currentNode->triggertarget != "" )
|
|
{
|
|
Entity *ent;
|
|
Event *event;
|
|
|
|
ent = NULL;
|
|
do
|
|
{
|
|
ent = G_FindTarget( ent, currentNode->triggertarget.c_str() );
|
|
if ( !ent )
|
|
{
|
|
break;
|
|
}
|
|
event = new Event( EV_Activate );
|
|
event->AddEntity( this );
|
|
ent->PostEvent( event, 0.0f );
|
|
}
|
|
while ( 1 );
|
|
}
|
|
|
|
}
|
|
|
|
currentNode = currentNode->GetNext();
|
|
}
|
|
|
|
lastTime = newTime;
|
|
|
|
speed_multiplier = splinePath->Eval( splineTime, pos, orient );
|
|
|
|
splineTime += level.frametime * speed_multiplier;
|
|
|
|
velocity = ( pos - origin ) * ( 1.0f / level.frametime );
|
|
if ( !ignoreangles )
|
|
{
|
|
if ( splineangles )
|
|
{
|
|
avelocity = ( orient - angles ) * ( 1.0f / level.frametime );
|
|
}
|
|
else
|
|
{
|
|
float len;
|
|
|
|
len = velocity.length();
|
|
if ( len > 0.05f )
|
|
{
|
|
Vector ang;
|
|
Vector dir;
|
|
float aroll;
|
|
|
|
aroll = avelocity[ ROLL ];
|
|
dir = velocity * ( 1.0f / len );
|
|
ang = dir.toAngles();
|
|
avelocity = ( ang - angles ) * ( 1.0f / level.frametime );
|
|
avelocity[ ROLL ] = aroll;
|
|
}
|
|
else
|
|
avelocity = vec_zero;
|
|
}
|
|
}
|
|
|
|
newTime = splineTime + 2.0f;
|
|
|
|
if ( newTime < 0 )
|
|
{
|
|
newTime = 0;
|
|
}
|
|
|
|
PostEvent( EV_ScriptSlave_FollowingPath, level.frametime );
|
|
|
|
}
|
|
|
|
void ScriptSlave::Explode( Event *ev )
|
|
{
|
|
float damage;
|
|
|
|
if ( ev->NumArgs() )
|
|
{
|
|
damage = ev->GetFloat( 1 );
|
|
}
|
|
else
|
|
{
|
|
damage = 120.0f;
|
|
}
|
|
|
|
CreateExplosion( origin, damage, this, this, this );
|
|
}
|
|
|
|
void ScriptSlave::NotShootable( Event *ev )
|
|
{
|
|
setContents( 0 );
|
|
}
|
|
|
|
void ScriptSlave::OpenPortal( Event *ev )
|
|
{
|
|
if ( !_portalOpen )
|
|
{
|
|
gi.AdjustAreaPortalState( this->edict, true );
|
|
_portalOpen = true;
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::ClosePortal( Event *ev )
|
|
{
|
|
if ( _portalOpen )
|
|
{
|
|
gi.AdjustAreaPortalState( this->edict, false );
|
|
_portalOpen = false;
|
|
}
|
|
}
|
|
|
|
void ScriptSlave::PhysicsOn( Event *ev )
|
|
{
|
|
commandswaiting = false;
|
|
setMoveType( MOVETYPE_BOUNCE );
|
|
setSolidType( SOLID_BBOX );
|
|
velocity = Vector(0, 0, 1);
|
|
edict->clipmask = MASK_SOLID|CONTENTS_BODY;
|
|
}
|
|
|
|
void ScriptSlave::PhysicsOff( Event *ev )
|
|
{
|
|
Event * event;
|
|
|
|
commandswaiting = false;
|
|
setMoveType( MOVETYPE_PUSH );
|
|
edict->clipmask = 0;
|
|
// become solid again
|
|
event = new Event( EV_Model );
|
|
event->AddString( model );
|
|
PostEvent( event, 0.0f );
|
|
}
|
|
|
|
void ScriptSlave::PhysicsVelocity( Event *ev )
|
|
{
|
|
velocity += ev->GetVector( 1 );
|
|
}
|
|
|
|
void ScriptSlave::StopEvent( Event *ev )
|
|
{
|
|
Stop();
|
|
}
|
|
|
|
void ScriptSlave::Stop( void )
|
|
{
|
|
thinking = false;
|
|
}
|
|
|
|
void ScriptSlave::ContinueEvent( Event *ev )
|
|
{
|
|
Continue();
|
|
}
|
|
|
|
void ScriptSlave::Continue( void )
|
|
{
|
|
thinking = true;
|
|
PostEvent( EV_ScriptSlave_FollowingPath, level.frametime );
|
|
}
|
|
|
|
//-----------------------------------------------------
|
|
//
|
|
// Name: Think
|
|
// Class: ScriptSlave
|
|
//
|
|
// Description: Processes the updates for the Script Slave.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//-----------------------------------------------------
|
|
void ScriptSlave::Think()
|
|
{
|
|
if(flags & FL_TOUCH_TRIGGERS)
|
|
{
|
|
G_TouchTriggers(this);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*QUAKED script_model (0 0.5 1) (0 0 0) (0 0 0) NOT_SOLID LIT_STATIC
|
|
|
|
******************************************************************************/
|
|
|
|
Event EV_ScriptModel_SetAnim
|
|
(
|
|
"anim",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"anim_name",
|
|
"Sets the script model's animation"
|
|
);
|
|
Event EV_ScriptModel_SetAnimDriven
|
|
(
|
|
"animdriven",
|
|
EV_DEFAULT,
|
|
"B",
|
|
"boolean",
|
|
"Sets the script model to be anim driven"
|
|
);
|
|
Event EV_ScriptModel_AnimOnce
|
|
(
|
|
"animonce",
|
|
EV_SCRIPTONLY,
|
|
"s",
|
|
"anim_name",
|
|
"Sets the script model's animation but only plays it once"
|
|
);
|
|
|
|
CLASS_DECLARATION( ScriptSlave, ScriptModel, "script_model" )
|
|
{
|
|
{ &EV_Gib, &ScriptModel::GibEvent },
|
|
{ &EV_SetAngle, &ScriptModel::SetAngleEvent },
|
|
{ &EV_ScriptModel_SetAnim, &ScriptModel::SetAnimEvent },
|
|
{ &EV_ScriptModel_SetAnimDriven, &ScriptModel::SetAnimDrivenEvent },
|
|
{ &EV_ScriptModel_AnimOnce, &ScriptModel::AnimOnceEvent },
|
|
{ &EV_Model, &ScriptModel::SetModelEvent },
|
|
|
|
{ NULL, NULL },
|
|
};
|
|
|
|
ScriptModel::ScriptModel()
|
|
{
|
|
// this is a tiki model
|
|
edict->s.eType = ET_MODELANIM;
|
|
animationDriven = false;
|
|
|
|
animate = new Animate( this );
|
|
}
|
|
|
|
void ScriptModel::Think( void )
|
|
{
|
|
total_delta = vec_zero;
|
|
ScriptSlave::Think();
|
|
|
|
if(animationDriven)
|
|
{
|
|
localangles = InterceptTargetXY( GetNewPosition(), Vector::Identity(), velocity.lengthXY() );
|
|
SetNewAngles( localangles );
|
|
setAngles( localangles );
|
|
|
|
// Set velocity based on current delta move
|
|
Vector forward;
|
|
Vector left;
|
|
Vector up;
|
|
localangles.AngleVectors( &forward, &left, &up );
|
|
|
|
total_delta /= level.frametime;
|
|
velocity = ( forward * total_delta[0] ) + ( left * total_delta[1] ) + ( up * total_delta[2] );
|
|
}
|
|
}
|
|
|
|
void ScriptModel::SetModelEvent( Event *ev )
|
|
{
|
|
char modelname[256] ;
|
|
char *tmpPtr ;
|
|
|
|
strcpy(modelname, ev->GetString( 1 ) );
|
|
tmpPtr = strstr(modelname, "*");
|
|
|
|
if (tmpPtr)
|
|
{
|
|
ev->SetString( 1 , tmpPtr );
|
|
}
|
|
|
|
ScriptSlave::SetModelEvent( ev );
|
|
setSolidType( SOLID_BBOX );
|
|
|
|
if ( ( gi.IsModel( edict->s.modelindex ) ) && !mins.length() && !maxs.length() )
|
|
{
|
|
gi.CalculateBounds( edict->s.modelindex, edict->s.scale, mins, maxs );
|
|
}
|
|
}
|
|
|
|
void ScriptModel::SetAnimEvent( Event *ev )
|
|
{
|
|
const char * const animname = ev->GetString( 1 );
|
|
if ( animname && strlen( animname ) && gi.IsModel( edict->s.modelindex ) )
|
|
{
|
|
int animnum = gi.Anim_NumForName( edict->s.modelindex, animname );
|
|
|
|
if ( animnum >= 0 )
|
|
{
|
|
animate->NewAnim( animnum );
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScriptModel::SetAnimDrivenEvent( Event *ev )
|
|
{
|
|
if ( (ev->NumArgs() > 0) && ( ev->GetBoolean( 1 ) == false ) )
|
|
{
|
|
animationDriven = false;
|
|
}
|
|
else
|
|
{
|
|
animationDriven = true;
|
|
turnThinkOn();
|
|
}
|
|
}
|
|
|
|
void ScriptModel::AnimOnceEvent( Event *ev )
|
|
{
|
|
const char * animname;
|
|
|
|
animname = ev->GetString( 1 );
|
|
if ( animname && strlen( animname ) && gi.IsModel( edict->s.modelindex ) )
|
|
{
|
|
animate->RandomAnimate( animname, EV_StopAnimating );
|
|
}
|
|
}
|
|
|
|
void ScriptModel::SetAngleEvent( Event *ev )
|
|
{
|
|
float angle;
|
|
|
|
angle = ev->GetFloat( 1 );
|
|
if ( angle == -1.0f )
|
|
{
|
|
ForwardDir = Vector( 0.0f, 0.0f, 90.0f );
|
|
localangles = Vector( -90.0f, 0.0f, 0.0f );
|
|
}
|
|
else if ( angle == -2.0f )
|
|
{
|
|
ForwardDir = Vector( 0.0f, 0.0f, -90.0f );
|
|
localangles = Vector( 90.0f, 0.0f, 0.0f );
|
|
}
|
|
else
|
|
{
|
|
ForwardDir = Vector( 0.0f, angle, 0.0f );
|
|
localangles = Vector( 0.0f, angle, 0.0f );
|
|
}
|
|
|
|
setAngles( localangles );
|
|
}
|
|
|
|
void ScriptModel::GibEvent( Event *ev )
|
|
{
|
|
int num,power;
|
|
float scale;
|
|
|
|
setSolidType( SOLID_NOT );
|
|
hideModel();
|
|
|
|
if ( !com_blood->integer )
|
|
{
|
|
PostEvent( EV_Remove, 0.0f );
|
|
return;
|
|
}
|
|
|
|
num = ev->GetInteger( 1 );
|
|
power = ev->GetInteger( 2 );
|
|
scale = ev->GetFloat( 3 );
|
|
|
|
power = -power;
|
|
|
|
if ( ev->NumArgs() > 3 )
|
|
{
|
|
CreateGibs( this, power, scale, num, ev->GetString( 4 ) );
|
|
}
|
|
else
|
|
{
|
|
CreateGibs( this, power, scale, num );
|
|
}
|
|
|
|
PostEvent( EV_Remove, 0.0f );
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*QUAKED script_origin (1.0 0 0) (-8 -8 -8) (8 8 8)
|
|
|
|
Used as an alternate origin for objects. Bind the object to the script_origin
|
|
in order to simulate changing that object's origin.
|
|
******************************************************************************/
|
|
|
|
CLASS_DECLARATION( ScriptSlave, ScriptOrigin, "script_origin" )
|
|
{
|
|
{ &EV_Model, &ScriptOrigin::SetModelEvent },
|
|
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
ScriptOrigin::ScriptOrigin()
|
|
{
|
|
setContents( 0 );
|
|
setSolidType( SOLID_NOT );
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*QUAKED script_skyorigin (1.0 0 0) ?
|
|
|
|
Used to specify the origin of a portal sky
|
|
******************************************************************************/
|
|
|
|
Event EV_ScriptSkyOrigin_SetBasePosition
|
|
(
|
|
"baseposition",
|
|
EV_SCRIPTONLY,
|
|
"v",
|
|
"base_position",
|
|
"Sets the base position of the sky origin."
|
|
);
|
|
Event EV_ScriptSkyOrigin_SetPlayerBasePosition
|
|
(
|
|
"playerbaseposition",
|
|
EV_SCRIPTONLY,
|
|
"v",
|
|
"base_position",
|
|
"Sets the base position for the player for the sky origin."
|
|
);
|
|
Event EV_ScriptSkyOrigin_SetTranslationMultiplier
|
|
(
|
|
"translationmult",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"translation_multiplier",
|
|
"Sets the translation multiplier for the sky origin."
|
|
);
|
|
Event EV_ScriptSkyOrigin_SetMaxDistance
|
|
(
|
|
"maxtranslationdist",
|
|
EV_SCRIPTONLY,
|
|
"f",
|
|
"max_translation_distance",
|
|
"Sets the maximum distance the sky origin will translate."
|
|
);
|
|
|
|
CLASS_DECLARATION( ScriptSlave, ScriptSkyOrigin, "script_skyorigin" )
|
|
{
|
|
{ &EV_ScriptSkyOrigin_SetBasePosition, &ScriptSkyOrigin::SetBasePosition },
|
|
{ &EV_ScriptSkyOrigin_SetPlayerBasePosition, &ScriptSkyOrigin::SetPlayerBasePosition },
|
|
{ &EV_ScriptSkyOrigin_SetTranslationMultiplier, &ScriptSkyOrigin::SetTranslationMultiplier },
|
|
{ &EV_ScriptSkyOrigin_SetMaxDistance, &ScriptSkyOrigin::SetMaxDistance },
|
|
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
ScriptSkyOrigin::ScriptSkyOrigin()
|
|
{
|
|
edict->s.renderfx |= RF_SKYORIGIN;
|
|
setContents( 0 );
|
|
setSolidType( SOLID_NOT );
|
|
turnThinkOn();
|
|
|
|
use_base_position = false;
|
|
use_player_base_position = false;
|
|
translation_multiplier = 0;
|
|
max_distance = 0;
|
|
}
|
|
|
|
void ScriptSkyOrigin::Think( void )
|
|
{
|
|
Vector delta;
|
|
Entity *player;
|
|
Vector new_origin;
|
|
|
|
new_origin = origin;
|
|
|
|
if ( use_base_position )
|
|
{
|
|
if ( translation_multiplier )
|
|
{
|
|
// Get player
|
|
|
|
player = g_entities[ 0 ].entity;
|
|
|
|
if ( !use_player_base_position )
|
|
{
|
|
// Get current player position
|
|
|
|
player_base_position = player->origin;
|
|
|
|
use_player_base_position = true;
|
|
}
|
|
|
|
// Calculate the new origin
|
|
|
|
delta = player->origin - player_base_position;
|
|
delta *= translation_multiplier;
|
|
|
|
if ( max_distance && ( delta.length() > max_distance ) )
|
|
{
|
|
delta.normalize();
|
|
delta *= max_distance;
|
|
}
|
|
|
|
new_origin = base_position + delta;
|
|
}
|
|
else
|
|
{
|
|
new_origin = base_position;
|
|
}
|
|
}
|
|
|
|
setOrigin( new_origin );
|
|
}
|
|
|
|
void ScriptSkyOrigin::SetBasePosition( Event *ev )
|
|
{
|
|
use_base_position = true;
|
|
base_position = ev->GetVector( 1 );
|
|
use_player_base_position = false;
|
|
}
|
|
|
|
void ScriptSkyOrigin::SetPlayerBasePosition( Event *ev )
|
|
{
|
|
use_player_base_position = true;
|
|
player_base_position = ev->GetVector( 1 );
|
|
}
|
|
|
|
void ScriptSkyOrigin::SetTranslationMultiplier( Event *ev )
|
|
{
|
|
translation_multiplier = ev->GetFloat( 1 );
|
|
}
|
|
|
|
void ScriptSkyOrigin::SetMaxDistance( Event *ev )
|
|
{
|
|
max_distance = ev->GetFloat( 1 );
|
|
}
|
|
|
|
|
|
//1ST PLAYABLE HACK STUFF
|
|
void ScriptSlave::Hack_AddParms( Event *ev )
|
|
{
|
|
_forcefieldNumber = ev->GetFloat( 1 );
|
|
_triggerNumber = ev->GetFloat( 2 );
|
|
}
|
|
|
|
void ScriptSlave::Hack_GetForceFieldNumber( Event *ev )
|
|
{
|
|
ev->ReturnFloat( _forcefieldNumber );
|
|
}
|
|
|
|
void ScriptSlave::Hack_GetScanner( Event *ev )
|
|
{
|
|
ev->ReturnEntity( _scanner );
|
|
}
|
|
|
|
void ScriptSlave::Hack_GetTriggerNumber( Event *ev )
|
|
{
|
|
ev->ReturnFloat( _triggerNumber );
|
|
}
|
|
|
|
void ScriptSlave::HandlesDamage( Event *ev )
|
|
{
|
|
_handlesDamage = ev->GetBoolean( 1 );
|
|
}
|
|
|
|
void ScriptSlave::setDamageEffect( Event *ev )
|
|
{
|
|
_damageEffect = ev->GetString( 1 );
|
|
}
|
|
|
|
void ScriptSlave::setBloodModel( Event *ev )
|
|
{
|
|
_bloodModel = ev->GetString( 1 );
|
|
}
|
|
|
|
void ScriptSlave::addRequiredDamageMOD( Event *ev )
|
|
{
|
|
str modname( ev->GetString( 1 ) );
|
|
assert( modname.length() > 0 );
|
|
_requiredMODlist.AddObject( modname );
|
|
|
|
}
|
|
|
|
void ScriptSlave::setCanBeAttackedByOtherSlaves(Event *ev)
|
|
{
|
|
_canBeAttackedByOtherScriptSlaves = ev->GetBoolean( 1 );
|
|
}
|