1005 lines
30 KiB
C++
1005 lines
30 KiB
C++
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Crytek Source code
|
|
// Copyright (c) Crytek 2001-2004
|
|
//
|
|
// File: ScriptObjectWeapon.cpp
|
|
//
|
|
// Description:
|
|
// ScriptObjectWeapon.cpp: implementation of the CScriptObjectWeapon class.
|
|
//
|
|
// History:
|
|
// - created by Marco C.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "ScriptObjectWeaponClass.h"
|
|
#include "ScriptObjectVector.h"
|
|
#include "WeaponClass.h"
|
|
#include "WeaponSystemEx.h"
|
|
#include <CryCharAnimationParams.h>
|
|
#include <float.h>
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
_DECLARE_SCRIPTABLEEX(CScriptObjectFireParam)
|
|
_DECLARE_SCRIPTABLEEX(CScriptObjectWeaponClass)
|
|
|
|
CScriptObjectFireParam::CScriptObjectFireParam()
|
|
{
|
|
}
|
|
CScriptObjectFireParam::~CScriptObjectFireParam()
|
|
{
|
|
}
|
|
|
|
bool CScriptObjectFireParam::Create(IScriptSystem *pScriptSystem,WeaponParams *p)
|
|
{
|
|
Init(pScriptSystem,this);
|
|
m_pWeaponParams=p;
|
|
|
|
if(!EnablePropertiesMapping(p))
|
|
{
|
|
CryError( "<CryGame> (CScriptObjectFireParam::Create) failed" );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
void CScriptObjectFireParam::InitializeTemplate(IScriptSystem *pSS)
|
|
{
|
|
_ScriptableEx<CScriptObjectFireParam>::InitializeTemplate(pSS);
|
|
AllowPropertiesMapping(pSS);
|
|
////set default as holding
|
|
RegisterProperty( "ai_mode",PROPERTY_TYPE_BOOL,offsetof(WeaponParams,bAIMode));
|
|
RegisterProperty( "allow_hold_breath",PROPERTY_TYPE_BOOL,offsetof(WeaponParams,bAllowHoldBreath));
|
|
RegisterProperty( "auto_aiming_dist",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fAutoAimDist));
|
|
RegisterProperty( "aim_recoil_modifier",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fAimRecoilModifier));
|
|
|
|
RegisterProperty( "accuracy_modifier_standing",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fAccuracyModifierStanding));
|
|
RegisterProperty( "accuracy_modifier_crouch",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fAccuracyModifierCrouch));
|
|
RegisterProperty( "accuracy_modifier_prone",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fAccuracyModifierProne));
|
|
RegisterProperty( "recoil_modifier_standing",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fRecoilModifierStanding));
|
|
RegisterProperty( "recoil_modifier_crouch",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fRecoilModifierCrouch));
|
|
RegisterProperty( "recoil_modifier_prone",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fRecoilModifierProne));
|
|
|
|
RegisterProperty( "min_accuracy",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fMinAccuracy));
|
|
RegisterProperty( "max_accuracy",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fMaxAccuracy));
|
|
RegisterProperty( "aim_improvement",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fAimImprovement));
|
|
RegisterProperty( "sprint_penalty",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fSprintPenalty));
|
|
RegisterProperty( "reload_time",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fReloadTime));
|
|
RegisterProperty( "fire_rate",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fFireRate));
|
|
RegisterProperty( "distance",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fDistance));
|
|
RegisterProperty( "damage",PROPERTY_TYPE_INT,offsetof(WeaponParams,nDamage));
|
|
RegisterProperty( "damage_drop_per_meters",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,fDamageDropPerMeters));
|
|
RegisterProperty( "bullet_per_shot",PROPERTY_TYPE_INT,offsetof(WeaponParams,nBulletpershot));
|
|
RegisterProperty( "fire_mode_type",PROPERTY_TYPE_INT,offsetof(WeaponParams,iFireModeType));
|
|
// projectile
|
|
RegisterProperty( "projectile_class",PROPERTY_TYPE_STRING,offsetof(WeaponParams,sProjectileClass));
|
|
RegisterProperty( "bullets_per_clip",PROPERTY_TYPE_INT,offsetof(WeaponParams,iBulletsPerClip));
|
|
RegisterProperty( "fire_activation",PROPERTY_TYPE_INT,offsetof(WeaponParams,fire_activation));
|
|
RegisterProperty( "max_recoil",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,max_recoil));
|
|
RegisterProperty( "min_recoil",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,min_recoil));
|
|
RegisterProperty( "no_ammo",PROPERTY_TYPE_BOOL,offsetof(WeaponParams,no_ammo));
|
|
RegisterProperty( "accuracy_decay_on_run",PROPERTY_TYPE_FLOAT,offsetof(WeaponParams,accuracy_decay_on_run));
|
|
}
|
|
|
|
void CScriptObjectFireParam::ReleaseTemplate()
|
|
{
|
|
_ScriptableEx<CScriptObjectFireParam>::ReleaseTemplate();
|
|
}
|
|
|
|
|
|
IScriptObject *CScriptObjectWeaponClass::m_pMemberBonePos = 0;
|
|
|
|
CScriptObjectWeaponClass::CScriptObjectWeaponClass()
|
|
{
|
|
m_pWeaponClass = 0;
|
|
}
|
|
|
|
CScriptObjectWeaponClass::~CScriptObjectWeaponClass()
|
|
{
|
|
// does not have to be deleted here ... it's managed by the weapon system
|
|
m_pWeaponClass = 0;
|
|
|
|
// these do have to be deleted, though ;)
|
|
while(!m_vFireParams.empty())
|
|
{
|
|
delete m_vFireParams.back();
|
|
m_vFireParams.pop_back();
|
|
}
|
|
}
|
|
|
|
bool CScriptObjectWeaponClass::Create(CXGame* pGame, CWeaponClass* pWeaponClass)
|
|
{
|
|
m_pGame = pGame;
|
|
m_pSystem = pGame->GetSystem();
|
|
m_pWeaponClass = pWeaponClass;
|
|
|
|
if (!m_pGame || !m_pSystem || !m_pWeaponClass)
|
|
return false;
|
|
|
|
Init(m_pSystem->GetIScriptSystem(), this);
|
|
|
|
m_pScriptThis->RegisterParent(this);
|
|
|
|
_SmartScriptObject pObj(m_pScriptSystem,true);
|
|
|
|
if (!m_pScriptSystem->GetGlobalValue(m_pWeaponClass->GetName().c_str(), pObj))
|
|
{
|
|
m_pSystem->GetILog()->LogToFile("[FATAL ERROR] Script table %s not found. Probably script was not loaded because of an error.",m_pWeaponClass->GetName().c_str());
|
|
return false;
|
|
}
|
|
m_pScriptThis->Clone(*pObj);
|
|
m_pScriptThis->SetValue("cnt", m_pScriptThis);
|
|
m_pScriptThis->SetValue("classid", m_pWeaponClass->GetID());
|
|
|
|
return true;
|
|
}
|
|
|
|
void CScriptObjectWeaponClass::InitializeTemplate(IScriptSystem *pSS)
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
m_pMemberBonePos = pSS->CreateObject();
|
|
|
|
_ScriptableEx<CScriptObjectWeaponClass>::InitializeTemplate(pSS);
|
|
REG_FUNC(CScriptObjectWeaponClass,SetName);
|
|
REG_FUNC(CScriptObjectWeaponClass,SetShaderFloat);
|
|
REG_FUNC(CScriptObjectWeaponClass,SetBindBone);
|
|
REG_FUNC(CScriptObjectWeaponClass,SetAnimationKeyEvent);
|
|
REG_FUNC(CScriptObjectWeaponClass,StartAnimation);
|
|
REG_FUNC(CScriptObjectWeaponClass,ResetAnimation);
|
|
REG_FUNC(CScriptObjectWeaponClass,GetAnimationLength);
|
|
REG_FUNC(CScriptObjectWeaponClass,GetCurAnimation);
|
|
REG_FUNC(CScriptObjectWeaponClass,IsAnimationRunning);
|
|
REG_FUNC(CScriptObjectWeaponClass,GetPos);
|
|
|
|
REG_FUNC(CScriptObjectWeaponClass,SetWeaponFireParams);
|
|
REG_FUNC(CScriptObjectWeaponClass,SetFirstPersonWeaponPos);
|
|
REG_FUNC(CScriptObjectWeaponClass,GetInstantHit);
|
|
//REG_FUNC(CScriptObjectWeapon,Mount);
|
|
REG_FUNC(CScriptObjectWeaponClass,GetBonePos);
|
|
REG_FUNC(CScriptObjectWeaponClass,GetProjectileFiringAngle);
|
|
REG_FUNC(CScriptObjectWeaponClass,Hit);
|
|
REG_FUNC(CScriptObjectWeaponClass,SetHoldingType);
|
|
|
|
REG_FUNC(CScriptObjectWeaponClass,LoadObject);
|
|
REG_FUNC(CScriptObjectWeaponClass,AttachObjectToBone);
|
|
REG_FUNC(CScriptObjectWeaponClass,DetachObjectToBone);
|
|
|
|
REG_FUNC(CScriptObjectWeaponClass,CacheObject);
|
|
|
|
REG_FUNC(CScriptObjectWeaponClass,DrawScopeFlare);
|
|
}
|
|
|
|
void CScriptObjectWeaponClass::ReleaseTemplate()
|
|
{
|
|
_ScriptableEx<CScriptObjectWeaponClass>::ReleaseTemplate();
|
|
SAFE_RELEASE( m_pMemberBonePos );
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::SetName(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(1);
|
|
const char *sName;
|
|
pH->GetParam(1,sName);
|
|
m_pWeaponClass->SetName(sName);
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::SetShaderFloat(IFunctionHandler *pH)
|
|
{
|
|
float fFloat,fFadeValue;
|
|
const char *sName;
|
|
int dwMask;
|
|
|
|
CHECK_PARAMETERS(4);
|
|
|
|
pH->GetParam(1, sName);
|
|
pH->GetParam(2, fFloat);
|
|
pH->GetParam(3, dwMask);
|
|
pH->GetParam(4, fFadeValue);
|
|
|
|
// set it for object
|
|
if ((dwMask) && m_pWeaponClass->GetObject())
|
|
m_pWeaponClass->GetObject()->SetShaderFloat(sName, fFloat);
|
|
|
|
// set it for character
|
|
if ((dwMask == 0) && m_pWeaponClass->GetCharacter())
|
|
m_pWeaponClass->GetCharacter()->SetShaderFloat(sName, fFloat);
|
|
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::SetBindBone(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(1);
|
|
const char *sBone;
|
|
pH->GetParam(1,sBone);
|
|
m_pWeaponClass->SetBindBone(sBone);
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CScriptObjectWeaponClass::SetAnimationKeyEvent(IFunctionHandler *pH)
|
|
{
|
|
if (pH->GetParamCount()<2 || pH->GetParamCount()>3)
|
|
{
|
|
m_pScriptSystem->RaiseError("CScriptObjectWeaponClass::SetAnimationKeyEvent wrong number of arguments");
|
|
return pH->EndFunctionNull();
|
|
};
|
|
|
|
const char *szAnimation;
|
|
int nFrameID;
|
|
USER_DATA udUserData = USER_DATA(-1);
|
|
pH->GetParam(1,szAnimation);
|
|
pH->GetParam(2,nFrameID);
|
|
if(pH->GetParamCount()>2)
|
|
pH->GetParam(3,udUserData);
|
|
|
|
if(m_pWeaponClass->GetCharacter())
|
|
{
|
|
m_pWeaponClass->GetCharacter()->AddAnimationEventSink(szAnimation, m_pWeaponClass);
|
|
m_pWeaponClass->GetCharacter()->AddAnimationEvent(szAnimation, nFrameID, (void*)udUserData);
|
|
}
|
|
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::StartAnimation(IFunctionHandler *pH)
|
|
{
|
|
if (!m_pWeaponClass->GetCharacter())
|
|
return pH->EndFunctionNull();
|
|
|
|
const char *animname;
|
|
int pos, layer=0;
|
|
bool bLooping = false;
|
|
bool bLoopSpecified = false;
|
|
float fBlendTime = 0.15f;
|
|
float fAniSpeed = 1.0f;
|
|
pH->GetParam(1,pos);
|
|
if (!pH->GetParam(2,animname))
|
|
{
|
|
//m_pGame->GetSystem()->Warning( VALIDATOR_MODULE_SYSTEM,VALIDATOR_WARNING,0,
|
|
// 0,"CScriptObjectWeaponClass::StartAnimation, animation name not specified, in WeaponClass %s", m_pWeaponClass->GetName().c_str() );
|
|
return pH->EndFunction(false);
|
|
}
|
|
|
|
if (pH->GetParamCount() > 2)
|
|
{
|
|
pH->GetParam(3,layer);
|
|
if (pH->GetParamCount() > 3)
|
|
{
|
|
pH->GetParam(4,fBlendTime);
|
|
if (pH->GetParamCount() > 4)
|
|
{
|
|
pH->GetParam(5,fAniSpeed);
|
|
if (pH->GetParamCount() > 5)
|
|
{
|
|
bLoopSpecified = true;
|
|
pH->GetParam(6,bLooping);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bLoopSpecified)
|
|
{
|
|
ICryCharInstance *pCharacter = m_pWeaponClass->GetCharacter();
|
|
if (pCharacter)
|
|
{
|
|
ICryAnimationSet *animSet = pCharacter->GetModel()->GetAnimationSet();
|
|
if (animSet)
|
|
{
|
|
int animId = animSet->Find(animname);
|
|
if (animId >= 0)
|
|
animSet->SetLoop( animId,bLooping );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (string(animname) == "NULL")
|
|
animname = 0;
|
|
|
|
m_pWeaponClass->GetCharacter()->SetAnimationSpeed( fAniSpeed );
|
|
|
|
bool result = false;
|
|
|
|
if (animname)
|
|
{
|
|
CryCharAnimationParams ccap;
|
|
ccap.fBlendInTime = fBlendTime;
|
|
ccap.fBlendOutTime = 0;
|
|
ccap.nLayerID = layer;
|
|
result = m_pWeaponClass->GetCharacter()->StartAnimation(animname,ccap);
|
|
|
|
//[PETAR] StartAnimation2 is now obsolete. Call commented and left as reference
|
|
//result = m_pWeaponClass->GetCharacter()->StartAnimation2(animname, fBlendTime, fBlendTime, layer, true, false);
|
|
}
|
|
else
|
|
result = m_pWeaponClass->GetCharacter()->StopAnimation(layer);
|
|
return pH->EndFunction(result);
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::ResetAnimation(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(1);
|
|
if (m_pWeaponClass->GetCharacter())
|
|
{
|
|
m_pWeaponClass->GetCharacter()->ResetAnimations();
|
|
}
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::GetAnimationLength(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(1);
|
|
const char *aniName;
|
|
pH->GetParam(1, aniName);
|
|
|
|
float length = 0.0f;
|
|
|
|
if (m_pWeaponClass->GetCharacter())
|
|
length = m_pWeaponClass->GetCharacter()->GetModel()->GetAnimationSet()->GetLength(aniName);
|
|
return pH->EndFunction(length);
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::GetCurAnimation(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(0);
|
|
|
|
if (m_pWeaponClass->GetCharacter())
|
|
{
|
|
if (m_pWeaponClass->GetCharacter()->GetCurAnimation() && m_pWeaponClass->GetCharacter()->GetCurAnimation()[0] != '\0')
|
|
|
|
return pH->EndFunction(m_pWeaponClass->GetCharacter()->GetCurAnimation());
|
|
}
|
|
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::IsAnimationRunning(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(0);
|
|
|
|
bool bResult=false;
|
|
if (m_pWeaponClass->GetCharacter())
|
|
if (m_pWeaponClass->GetCharacter()->GetCurAnimation())
|
|
bResult=true;
|
|
|
|
return pH->EndFunction(bResult);
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::GetPos(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(0);
|
|
CScriptObjectVector oVec(m_pScriptSystem);
|
|
|
|
oVec=m_pWeaponClass->GetPos();
|
|
|
|
return pH->EndFunction(*oVec);
|
|
}
|
|
|
|
/*! Adds a set of fire-parameters
|
|
@param pObj table of fireparams (accuracy, ammo, max_ammo, reload_time, fire_rate, distance, damage, blast_radius, bullet_per_shot, instant, projectile_mass, projectile_size, projectile_velocity, acc_thrust, acc_lift, air_resistance, gravity, surface_idx, projectile_class, fx, fy, bullets_per_clip)
|
|
*/
|
|
int CScriptObjectWeaponClass::SetWeaponFireParams(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(1);
|
|
_SmartScriptObject pObj(m_pScriptSystem,true);
|
|
|
|
WeaponParams s;
|
|
s.fDamageDropPerMeters=0;
|
|
|
|
pH->GetParam(1,*pObj);
|
|
pObj->BeginSetGetChain();
|
|
|
|
pObj->GetValueChain( "ai_mode", s.bAIMode );
|
|
pObj->GetValueChain( "allow_hold_breath",s.bAllowHoldBreath);
|
|
pObj->GetValueChain( "auto_aiming_dist",s.fAutoAimDist );
|
|
pObj->GetValueChain( "min_accuracy", s.fMinAccuracy );
|
|
pObj->GetValueChain( "max_accuracy", s.fMaxAccuracy );
|
|
pObj->GetValueChain( "aim_improvement", s.fAimImprovement );
|
|
pObj->GetValueChain( "sprint_penalty", s.fSprintPenalty );
|
|
pObj->GetValueChain( "aim_recoil_modifier", s.fAimRecoilModifier );
|
|
pObj->GetValueChain( "reload_time", s.fReloadTime );
|
|
pObj->GetValueChain( "fire_rate", s.fFireRate );
|
|
pObj->GetValueChain( "tap_fire_rate", s.fTapFireRate );
|
|
pObj->GetValueChain( "distance", s.fDistance );
|
|
pObj->GetValueChain( "damage", s.nDamage );
|
|
pObj->GetValueChain( "damage_drop_per_meter",s.fDamageDropPerMeters );
|
|
pObj->GetValueChain( "bullet_per_shot", s.nBulletpershot );
|
|
pObj->GetValueChain( "fire_mode_type", s.iFireModeType );
|
|
pObj->GetValueChain( "shoot_underwater",s.bShootUnderwater );
|
|
|
|
// accuracy and recoil modifier
|
|
pObj->GetValueChain( "accuracy_modifier_standing", s.fAccuracyModifierStanding );
|
|
pObj->GetValueChain( "accuracy_modifier_crouch", s.fAccuracyModifierCrouch );
|
|
pObj->GetValueChain( "accuracy_modifier_prone", s.fAccuracyModifierProne );
|
|
pObj->GetValueChain( "recoil_modifier_standing", s.fRecoilModifierStanding );
|
|
pObj->GetValueChain( "recoil_modifier_crouch", s.fRecoilModifierCrouch );
|
|
pObj->GetValueChain( "recoil_modifier_prone", s.fRecoilModifierProne );
|
|
|
|
// projectile
|
|
const char *sClass = NULL;
|
|
pObj->GetValueChain( "projectile_class", sClass);
|
|
if (sClass)
|
|
s.sProjectileClass = sClass;
|
|
|
|
pObj->GetValueChain( "bullets_per_clip", s.iBulletsPerClip);
|
|
pObj->GetValueChain( "fire_activation", s.fire_activation);
|
|
pObj->GetValueChain( "min_recoil", s.min_recoil);
|
|
pObj->GetValueChain( "max_recoil", s.max_recoil);
|
|
pObj->GetValueChain( "no_ammo", s.no_ammo);
|
|
pObj->GetValueChain( "accuracy_decay_on_run", s.accuracy_decay_on_run);
|
|
if (!pObj->GetValueChain( "whizz_sound_radius", s.whizz_sound_radius))
|
|
s.whizz_sound_radius=0.0f;
|
|
s.whizz_sound_radius*=s.whizz_sound_radius; // keep it squared
|
|
if (!pObj->GetValueChain( "iImpactForceMul", s.iImpactForceMul))
|
|
s.iImpactForceMul = 2;
|
|
if (!pObj->GetValueChain( "iImpactForceMulFinal", s.iImpactForceMulFinal))
|
|
s.iImpactForceMulFinal = 10;
|
|
if (!pObj->GetValueChain( "iImpactForceMulFinalTorso", s.iImpactForceMulFinalTorso))
|
|
s.iImpactForceMulFinalTorso = 0;
|
|
|
|
pObj->EndSetGetChain();
|
|
|
|
int nFireParamIndex=m_vFireParams.size();
|
|
|
|
CScriptObjectFireParam *pFireParamObj=new CScriptObjectFireParam;
|
|
|
|
WeaponParams *pReadAddress=m_pWeaponClass->AddWeaponParams( s );
|
|
pFireParamObj->Create(m_pScriptSystem,pReadAddress);
|
|
m_vFireParams.push_back(pFireParamObj);
|
|
pFireParamObj->GetScriptObject()->Clone(pObj);
|
|
_SmartScriptObject soCnt(m_pScriptSystem, true);
|
|
if (m_pScriptThis->GetValue("cnt", soCnt))
|
|
{
|
|
soCnt->SetAt(nFireParamIndex, pFireParamObj->GetScriptObject());
|
|
}
|
|
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*! Sets the first-person-weapon position and orientation
|
|
@param v3Pos position of weapon
|
|
@param v3Angles orientation of weapon
|
|
*/
|
|
int CScriptObjectWeaponClass::SetFirstPersonWeaponPos(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(2);
|
|
CScriptObjectVector oVec(m_pScriptSystem,true);
|
|
Vec3d v3Pos;
|
|
Vec3d v3Angles;
|
|
pH->GetParam(1,*oVec);
|
|
v3Pos=oVec.Get();
|
|
pH->GetParam(2,*oVec);
|
|
v3Angles=oVec.Get();
|
|
m_pWeaponClass->SetFirstPersonWeaponPos(v3Pos,v3Angles);
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#define MAX_HITS 4
|
|
/*! Traces a ray to determine what and where an instant weapon hits
|
|
@param pObj ray-description-table (shooter, pos, angles, dir, distance)
|
|
@return target-description-table (objtype (0=entity, 1=stat-obj, 2=terrain), pos, normal, dir, target (nil if objtype!=0))
|
|
*/
|
|
int CScriptObjectWeaponClass::GetInstantHit(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(1);
|
|
_SmartScriptObject pObj(m_pScriptSystem,true);
|
|
_SmartScriptObject pTempObj(m_pScriptSystem,true);
|
|
CScriptObjectVector oVec(m_pScriptSystem,true);
|
|
CScriptObjectVector oVec1(m_pScriptSystem,false);
|
|
CScriptObjectVector oVec2(m_pScriptSystem,false);
|
|
CScriptObjectVector oVec3(m_pScriptSystem,false);
|
|
|
|
IEntity *shooter;
|
|
int nID;
|
|
Vec3d pos, angles, dir;
|
|
float fDistance;
|
|
int res;
|
|
|
|
pH->GetParam(1,*pObj);
|
|
pObj->GetValue( "shooter",*pTempObj );
|
|
pTempObj->GetValue("id",nID);
|
|
|
|
shooter= m_pSystem->GetIEntitySystem()->GetEntity(nID);
|
|
if(shooter==NULL)
|
|
{
|
|
TRACE("CScriptObjectWeapon::GetInstantHit() shooter in nil");
|
|
return pH->EndFunctionNull();
|
|
}
|
|
pObj->GetValue( "pos", *oVec );
|
|
pos=oVec.Get();
|
|
pObj->GetValue( "angles", *oVec );
|
|
angles=oVec.Get();
|
|
pObj->GetValue( "dir", *oVec );
|
|
dir=oVec.Get();
|
|
pObj->GetValue( "distance", fDistance );
|
|
dir*=fDistance;
|
|
|
|
IPhysicalEntity *skip=shooter->GetPhysics();
|
|
|
|
ray_hit hits[MAX_HITS];
|
|
res=m_pSystem->GetIPhysicalWorld()->RayWorldIntersection(pos,dir, ent_all, 0,hits,MAX_HITS, skip);
|
|
if(res){
|
|
_SmartScriptObject pTable(m_pScriptSystem);
|
|
for(int nCount=0;nCount<MAX_HITS;nCount++)
|
|
{
|
|
_SmartScriptObject pOut(m_pScriptSystem);
|
|
CScriptObjectVector oVec1(m_pScriptSystem);
|
|
CScriptObjectVector oVec2(m_pScriptSystem);
|
|
CScriptObjectVector oVec3(m_pScriptSystem);
|
|
int objecttype;
|
|
if(hits[nCount].dist<=0)
|
|
continue;
|
|
IEntity *centycontact = NULL;
|
|
if (res && hits[nCount].dist>0 && hits[nCount].pCollider)
|
|
{
|
|
centycontact = (IEntity *)hits[nCount].pCollider->GetForeignData();
|
|
if (centycontact && centycontact->IsGarbage())
|
|
{
|
|
res = 0;
|
|
}
|
|
if (centycontact && (!centycontact->IsGarbage()))
|
|
objecttype = OT_ENTITY;
|
|
else
|
|
objecttype = OT_STAT_OBJ;
|
|
}
|
|
|
|
if (hits[nCount].pCollider)
|
|
{
|
|
if (centycontact)
|
|
{
|
|
objecttype=0; // entity
|
|
pOut->SetValue("target", centycontact->GetId());
|
|
}
|
|
else
|
|
{
|
|
objecttype=1; // stat obj
|
|
pOut->SetToNull("target");
|
|
}
|
|
}else
|
|
{
|
|
objecttype=2; // terrain
|
|
pOut->SetToNull("target");
|
|
}
|
|
|
|
pOut->SetValue("objtype", objecttype);
|
|
oVec1=(Vec3d)hits[nCount].pt;
|
|
pOut->SetValue("pos", *oVec1);
|
|
oVec2=(Vec3d)hits[nCount].n;
|
|
pOut->SetValue("normal", *oVec2);
|
|
oVec3=GetNormalized(dir);
|
|
pOut->SetValue( "dir", *oVec3 );
|
|
pOut->SetValue( "surfaceid", hits[nCount].surface_idx );
|
|
pOut->SetValue( "partid", hits[nCount].partid);
|
|
pOut->SetValue( "shooter",nID);
|
|
|
|
pTable->SetAt(nCount,pOut);
|
|
if (res && hits[0].dist>0)
|
|
break;
|
|
}
|
|
return pH->EndFunction(pTable);
|
|
}
|
|
else{
|
|
return pH->EndFunctionNull();
|
|
}
|
|
}
|
|
|
|
/*! Makes sure mounted weapons are updated
|
|
*/
|
|
/*int CScriptObjectWeapon::Mount(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(0);
|
|
|
|
m_pWeapon->Mount(true);
|
|
|
|
return pH->EndFunctionNull();
|
|
}*/
|
|
|
|
|
|
/*! Obtains the position of a bone in the weapon object while taking into account
|
|
that weapons are rendered with a different FOV
|
|
@param sBoneName Name of the bone
|
|
*/
|
|
int CScriptObjectWeaponClass::GetBonePos(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(1);
|
|
|
|
const char * sBoneName = "wt";
|
|
pH->GetParam(1,sBoneName);
|
|
|
|
ICryCharInstance * cmodel = m_pWeaponClass->GetCharacter();
|
|
|
|
if (!cmodel)
|
|
return pH->EndFunctionNull();
|
|
|
|
ICryBone * pBone = cmodel->GetBoneByName(sBoneName);
|
|
if(!pBone)
|
|
{
|
|
return pH->EndFunctionNull();
|
|
}
|
|
|
|
Vec3d vBonePos = pBone->GetBonePosition();
|
|
Vec3d angles = m_pWeaponClass->GetAngles();
|
|
|
|
Matrix44 m=Matrix34::CreateRotationXYZ( Deg2Rad(angles), m_pWeaponClass->GetPos() ); //set rotation and translation in one function call
|
|
m = GetTransposed44(m); //TODO: remove this after E3 and use Matrix34 instead of Matrix44
|
|
|
|
// get result
|
|
Vec3 vec = m.TransformPointOLD(vBonePos);
|
|
|
|
m_pMemberBonePos->BeginSetGetChain();
|
|
m_pMemberBonePos->SetValueChain("x",vec.x);
|
|
m_pMemberBonePos->SetValueChain("y",vec.y);
|
|
m_pMemberBonePos->SetValueChain("z",vec.z);
|
|
m_pMemberBonePos->EndSetGetChain();
|
|
|
|
return pH->EndFunction(m_pMemberBonePos);
|
|
}
|
|
|
|
/*! Calculate the needed firing angle to fire a projectile with the
|
|
passed properties to the passed spot
|
|
@param v Velocity of the projectile
|
|
@param g Gravity of the projectile
|
|
@param x horizontal distance to the required impact point
|
|
@param y vertical distance between shooter and projectile impact point
|
|
|
|
|
|
input: x - horizontal distance to target (always positive), y - vertical distance to target (pisitive or negative), v - initial particle velocity (scalar, positive), g - gravity (positive scalar, assume that it vector points down)
|
|
|
|
d = sqrt(v^4 - 2*g*y*v^2-g^2*x^2)
|
|
(if expression is negative, no solution)
|
|
a = v^2-g*y
|
|
t = sqrt(2*(a+d)/g^2)
|
|
angle = acos(x/(v*t))
|
|
|
|
then compute y_test = v*sin_tpl(angle)*t-g*t^2/2,
|
|
if (y_test*y<0 (false root) && a-d>0), try t = sqrt(2*(a-d)/g^2) (else no solution)
|
|
|
|
|
|
|
|
*/
|
|
int CScriptObjectWeaponClass::GetProjectileFiringAngle(IFunctionHandler *pH)
|
|
{
|
|
|
|
float x,y,v,g;
|
|
CHECK_PARAMETERS(4);
|
|
|
|
pH->GetParam(1, v);
|
|
pH->GetParam(2, g);
|
|
pH->GetParam(3, x);
|
|
pH->GetParam(4, y);
|
|
|
|
float angle=0.0,t,a;
|
|
|
|
// Avoid square root in script
|
|
float d = cry_sqrtf(powf(v,4)-2*g*y*powf(v,2)-powf(g,2)*powf(x,2));
|
|
if(d>=0)
|
|
{
|
|
a=powf(v,2)-g*y;
|
|
if (a-d>0) {
|
|
t=cry_sqrtf(2*(a-d)/powf(g,2));
|
|
angle = (float)acos_tpl(x/(v*t));
|
|
float y_test;
|
|
y_test=float(-v*sin_tpl(angle)*t-g*powf(t,2)/2);
|
|
if (fabsf(y-y_test)<0.02f)
|
|
return pH->EndFunction(RAD2DEG(-angle));
|
|
y_test=float(v*sin_tpl(angle)*t-g*pow(t,2)/2);
|
|
if (fabsf(y-y_test)<0.02f)
|
|
return pH->EndFunction(RAD2DEG(angle));
|
|
}
|
|
t = cry_sqrtf(2*(a+d)/powf(g,2));
|
|
angle = (float)acos_tpl(x/(v*t));
|
|
float y_test=float(v*sin_tpl(angle)*t-g*pow(t,2)/2);
|
|
|
|
if (fabsf(y-y_test)<0.02f)
|
|
return pH->EndFunction(RAD2DEG(angle));
|
|
|
|
return pH->EndFunction(0);
|
|
}
|
|
return pH->EndFunction(0);
|
|
}
|
|
|
|
|
|
int CScriptObjectWeaponClass::Hit(IFunctionHandler *pH)
|
|
{
|
|
_SmartScriptObject pHit(m_pScriptSystem,true);
|
|
_SmartScriptObject pObj(m_pScriptSystem,true);
|
|
CScriptObjectVector oVec(m_pScriptSystem,true);
|
|
if(pH->GetParam(1,pHit))
|
|
{
|
|
if(pHit->Count())
|
|
{
|
|
pHit->BeginIteration();
|
|
while (pHit->MoveNext())
|
|
{
|
|
if(pHit->GetCurrent(pObj))
|
|
{
|
|
int idShooter,idTarget,objtype,partid,surfaceid;
|
|
pObj->BeginSetGetChain();
|
|
|
|
SWeaponHit hit;
|
|
pObj->GetValueChain("pos",oVec);
|
|
hit.pos = oVec.Get();
|
|
pObj->GetValueChain("dir",oVec);
|
|
hit.dir = GetNormalized(((Vec3d&)oVec));
|
|
pObj->GetValueChain("normal",oVec);
|
|
hit.normal = oVec.Get();
|
|
pObj->GetValueChain("target",idTarget);
|
|
hit.target = m_pSystem->GetIEntitySystem()->GetEntity(idTarget);
|
|
pObj->GetValueChain("partid",partid);
|
|
hit.ipart = partid;
|
|
pObj->GetValueChain("objectype",objtype);
|
|
hit.objecttype =objtype;
|
|
pObj->GetValueChain("shooter",idShooter);
|
|
hit.shooter = m_pSystem->GetIEntitySystem()->GetEntity(idShooter);
|
|
hit.weapon = m_pWeaponClass->GetScriptObject();
|
|
hit.projectile = 0; // Instant weapon, no projectiles.
|
|
hit.damage = (float)m_pWeaponClass->m_fireParams.nDamage;
|
|
hit.iImpactForceMul = m_pWeaponClass->m_fireParams.iImpactForceMul;
|
|
hit.iImpactForceMulFinal = m_pWeaponClass->m_fireParams.iImpactForceMulFinal;
|
|
hit.iImpactForceMulFinalTorso = m_pWeaponClass->m_fireParams.iImpactForceMulFinalTorso;
|
|
pObj->GetValueChain("surfaceid",surfaceid);
|
|
hit.surface_id=surfaceid;
|
|
hit.weapon_death_anim_id = m_pWeaponClass->m_fireParams.iDeathAnim;
|
|
// hit.iNumBullets = iNumShots;
|
|
pObj->EndSetGetChain();
|
|
//m_pWeaponClass->ProcessHit(hit);
|
|
}
|
|
}
|
|
pHit->EndIteration();
|
|
}
|
|
}
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
|
|
/*
|
|
*/
|
|
int CScriptObjectWeaponClass::SetHoldingType(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(1);
|
|
// int iCrosshairIdx;
|
|
int type;
|
|
pH->GetParam(1, type);
|
|
m_pWeaponClass->m_HoldingType = type;
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::LoadObject(IFunctionHandler *pH)
|
|
{
|
|
char *geometryName;
|
|
pH->GetParam(1, geometryName);
|
|
|
|
m_pWeaponClass->LoadMuzzleFlash(geometryName);
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
int CScriptObjectWeaponClass::AttachObjectToBone(IFunctionHandler *pH)
|
|
{
|
|
char *boneName;
|
|
pH->GetParam(2, boneName);
|
|
|
|
if (m_pWeaponClass->GetCharacter() && m_pWeaponClass->GetMuzzleFlash())
|
|
{
|
|
int boneid = m_pWeaponClass->GetCharacter()->GetModel()->GetBoneByName(boneName);
|
|
if (boneid >= 0)
|
|
{
|
|
ICryCharInstance::ObjectBindingHandle boneHandler;
|
|
boneHandler = m_pWeaponClass->GetCharacter()->AttachToBone(m_pWeaponClass->GetMuzzleFlash(), boneid);
|
|
|
|
// Make user data for bone handler.
|
|
USER_DATA ud = m_pScriptSystem->CreateUserData( boneHandler,USER_DATA_BONEHANDLER );
|
|
return pH->EndFunction(ud);
|
|
}
|
|
}
|
|
|
|
return pH->EndFunctionNull();
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------------------------
|
|
int CScriptObjectWeaponClass::DetachObjectToBone(IFunctionHandler *pH)
|
|
{
|
|
char *boneName;
|
|
pH->GetParam(1,boneName);
|
|
|
|
int BAD_HANDLER = -1;
|
|
int nCookie;
|
|
ULONG_PTR boneHandler = BAD_HANDLER;
|
|
|
|
if (!pH->GetParamUDVal(2,boneHandler,nCookie))
|
|
{
|
|
boneHandler = BAD_HANDLER;
|
|
}
|
|
if (nCookie != USER_DATA_BONEHANDLER)
|
|
{
|
|
boneHandler = BAD_HANDLER;
|
|
}
|
|
|
|
if (m_pWeaponClass->GetCharacter())
|
|
{
|
|
if (boneHandler == -1)
|
|
{
|
|
m_pWeaponClass->GetCharacter()->AttachObjectToBone( NULL, boneName, false );
|
|
}
|
|
else
|
|
{
|
|
m_pWeaponClass->GetCharacter()->Detach( boneHandler );
|
|
}
|
|
}
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::CacheObject(IFunctionHandler *pH)
|
|
{
|
|
CHECK_PARAMETERS(1);
|
|
char *geometryName;
|
|
pH->GetParam(1, geometryName);
|
|
|
|
m_pWeaponClass->GetWeaponSystem().CacheObject(geometryName);
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
int CScriptObjectWeaponClass::DrawScopeFlare(IFunctionHandler *pH)
|
|
{
|
|
CScriptObjectVector oVec(m_pScriptSystem,true);
|
|
_SmartScriptObject pObj(m_pScriptSystem,true);
|
|
|
|
if (!pH->GetParam(1,*pObj))
|
|
return pH->EndFunction(-1);
|
|
|
|
IScriptObject *pITable=*pObj;
|
|
|
|
if (!pITable->BeginSetGetChain())
|
|
return pH->EndFunction(-1);
|
|
|
|
CDLight DynLight;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
const char *sShaderName=NULL;
|
|
|
|
if (!pITable->GetValueChain( "lightShader",sShaderName))
|
|
m_pScriptSystem->RaiseError( "<DrawScopeFlare> sShaderName not specified" );
|
|
|
|
DynLight.m_Flags = DLF_POINT;
|
|
|
|
DynLight.m_pShader = m_pGame->GetSystem()->GetIRenderer()->EF_LoadShader(sShaderName, eSH_World);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// cast shadows
|
|
int nThisAreaOnly = 0;
|
|
if (!pITable->GetValueChain("areaonly",nThisAreaOnly))
|
|
m_pScriptSystem->RaiseError( "<DrawScopeFlare> thisareaonly not specified" );
|
|
else
|
|
{
|
|
if (nThisAreaOnly==1)
|
|
DynLight.m_Flags |= DLF_THIS_AREA_ONLY;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// shaders stuff
|
|
DynLight.m_Flags |= DLF_LIGHTSOURCE;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// more shaders stuff
|
|
DynLight.m_pLightImage = NULL;
|
|
DynLight.m_Flags |= DLF_POINT;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int shooterid;
|
|
float factor;
|
|
IEntity* pShooter = NULL;
|
|
if (pITable->GetValueChain("shooterid", shooterid))
|
|
{
|
|
pShooter = m_pGame->GetSystem()->GetIEntitySystem()->GetEntity(shooterid);
|
|
assert(pShooter);
|
|
if (pShooter->GetEntityVisArea() != 0)
|
|
return pH->EndFunction();
|
|
|
|
IEntity* pPlayer = m_pGame->GetMyPlayer();
|
|
|
|
if (pPlayer == NULL)
|
|
return pH->EndFunction();
|
|
|
|
if (pPlayer == pShooter)
|
|
return pH->EndFunction();
|
|
|
|
CPlayer *pShooterPlayer=NULL;
|
|
if (pShooter->GetContainer()) pShooter->GetContainer()->QueryContainerInterface(CIT_IPLAYER,(void**) &pShooterPlayer);
|
|
assert(pShooterPlayer);
|
|
|
|
// position flare relative to weapon_bone
|
|
if (pShooter->GetCharInterface()->GetCharacter(0) == NULL)
|
|
return pH->EndFunction();
|
|
|
|
ICryBone *pBone = pShooter->GetCharInterface()->GetCharacter(0)->GetBoneByName("weapon_bone");
|
|
|
|
if (!pBone)
|
|
return pH->EndFunction();
|
|
|
|
Vec3 rot = pShooterPlayer->GetActualAngles();
|
|
rot.x = 0;
|
|
rot.z = pShooterPlayer->m_LegAngle;
|
|
Matrix33 shooterMatrix = Matrix33::CreateRotationXYZ( Deg2Rad(rot));
|
|
|
|
DynLight.m_Origin = pShooter->GetPos() + shooterMatrix * (pBone->GetBonePosition() + 0.1f*pBone->GetBoneAxis('z'));
|
|
|
|
Vec3 vPlayerDir;
|
|
GetDirection(pPlayer, vPlayerDir);
|
|
Vec3 vShooterDir = pBone->GetBoneAxis('x');
|
|
vShooterDir = shooterMatrix * vShooterDir;
|
|
|
|
Vec3 diff = pShooter->GetPos() - pPlayer->GetPos();
|
|
diff.Normalize();
|
|
|
|
factor = fabs(2.0f * (vPlayerDir.Dot(diff) - 0.3f));
|
|
factor = FClamp(factor, 0, 1);
|
|
factor = -vShooterDir.Dot(diff) * factor;
|
|
|
|
const float fAngle=30.0f * gf_DEGTORAD; // -30..30
|
|
|
|
float fAngleCos=cry_cosf(fAngle);
|
|
|
|
factor = (factor-fAngleCos)/(1.0f-fAngleCos);
|
|
|
|
float f=m_pGame->GetSystem()->GetITimer()->GetCurrTime()*7.0f;
|
|
|
|
float fNoise= (cry_sinf(f*3.0f) + cry_sinf(f*2.0f) + cry_sinf(f*5.0f + 1.0f))/3.0f; // -1..1
|
|
|
|
factor -= 0.3f* (fNoise*0.5f+0.5f);
|
|
|
|
if(factor < 0)
|
|
factor = 0;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (!pITable->GetValueChain( "orad",DynLight.m_fRadius))
|
|
return pH->EndFunction();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (!pITable->GetValueChain( "coronaScale", DynLight.m_fCoronaScale))
|
|
return pH->EndFunction();
|
|
|
|
DynLight.m_fCoronaScale*= factor;
|
|
|
|
Vec3 vSunColor = m_pGame->GetSystem()->GetI3DEngine()->GetSunColor();
|
|
DynLight.m_Color = CFColor (vSunColor.x, vSunColor.y, vSunColor.z) * 1.0f * DynLight.m_fCoronaScale;
|
|
DynLight.m_Color.Clamp();
|
|
|
|
DynLight.m_SpecColor.Set(1, 1, 1, 1);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// finally add it to the engine
|
|
m_pGame->GetSystem()->GetIRenderer()->EF_UpdateDLight(&DynLight);
|
|
|
|
m_pGame->GetSystem()->GetI3DEngine()->AddDynamicLightSource(DynLight, pShooter);
|
|
|
|
if (DynLight.m_pShader->GetRefCount() == 1)
|
|
DynLight.m_pShader->AddRef();
|
|
}
|
|
|
|
pITable->EndSetGetChain();
|
|
|
|
return pH->EndFunction();
|
|
}
|
|
|
|
void CScriptObjectWeaponClass::GetDirection(IEntity *pEntity, Vec3& vDir)
|
|
{
|
|
Matrix44 tm;
|
|
|
|
vDir.Set(0,-1,0);
|
|
tm.SetIdentity();
|
|
tm=Matrix44::CreateRotationZYX(-pEntity->GetAngles()*gf_DEGTORAD)*tm; //NOTE: angles in radians and negated
|
|
vDir = GetTransposed44(tm)*vDir;
|
|
} |