2013-09-21 04:17:34 +09:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 yvt
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
This file is part of OpenSpades.
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
OpenSpades is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
OpenSpades is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
*/
|
|
|
|
|
2019-05-25 12:18:32 +09:00
|
|
|
#include <algorithm>
|
2017-01-06 04:01:10 +09:00
|
|
|
#include <array>
|
2019-05-25 12:18:32 +09:00
|
|
|
#include <cmath>
|
2016-12-03 18:23:47 +09:00
|
|
|
#include <cstdlib>
|
2013-09-21 04:17:34 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
#include "CTFGameMode.h"
|
|
|
|
#include "Client.h"
|
2013-09-21 04:17:34 +09:00
|
|
|
#include "ClientPlayer.h"
|
2017-01-06 04:01:10 +09:00
|
|
|
#include "GameMap.h"
|
2016-12-03 18:23:47 +09:00
|
|
|
#include "GunCasing.h"
|
|
|
|
#include "IAudioChunk.h"
|
|
|
|
#include "IAudioDevice.h"
|
2013-09-21 04:17:34 +09:00
|
|
|
#include "IImage.h"
|
|
|
|
#include "IModel.h"
|
|
|
|
#include "IRenderer.h"
|
2016-12-03 18:23:47 +09:00
|
|
|
#include "Player.h"
|
|
|
|
#include "Weapon.h"
|
2013-09-21 04:17:34 +09:00
|
|
|
#include "World.h"
|
|
|
|
#include <Core/Settings.h>
|
|
|
|
#include <ScriptBindings/IBlockSkin.h>
|
|
|
|
#include <ScriptBindings/IGrenadeSkin.h>
|
2016-12-03 18:23:47 +09:00
|
|
|
#include <ScriptBindings/ISpadeSkin.h>
|
|
|
|
#include <ScriptBindings/IThirdPersonToolSkin.h>
|
|
|
|
#include <ScriptBindings/IToolSkin.h>
|
|
|
|
#include <ScriptBindings/IViewToolSkin.h>
|
2013-09-21 04:17:34 +09:00
|
|
|
#include <ScriptBindings/IWeaponSkin.h>
|
2016-12-03 18:23:47 +09:00
|
|
|
#include <ScriptBindings/ScriptFunction.h>
|
2013-09-21 04:17:34 +09:00
|
|
|
|
2016-11-19 21:03:51 +09:00
|
|
|
SPADES_SETTING(cg_ragdoll);
|
|
|
|
SPADES_SETTING(cg_ejectBrass);
|
2016-11-20 18:13:49 +09:00
|
|
|
DEFINE_SPADES_SETTING(cg_animations, "1");
|
2016-11-22 01:16:28 +09:00
|
|
|
SPADES_SETTING(cg_shake);
|
2017-01-07 01:38:56 +09:00
|
|
|
DEFINE_SPADES_SETTING(cg_environmentalAudio, "1");
|
2017-03-04 03:44:57 +09:00
|
|
|
DEFINE_SPADES_SETTING(cg_viewWeaponX, "0");
|
|
|
|
DEFINE_SPADES_SETTING(cg_viewWeaponY, "0");
|
|
|
|
DEFINE_SPADES_SETTING(cg_viewWeaponZ, "0");
|
2013-09-21 04:17:34 +09:00
|
|
|
|
|
|
|
namespace spades {
|
|
|
|
namespace client {
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
class SandboxedRenderer : public IRenderer {
|
|
|
|
Handle<IRenderer> base;
|
|
|
|
AABB3 clipBox;
|
|
|
|
bool allowDepthHack;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void OnProhibitedAction() {}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
bool CheckVisibility(const AABB3 &box) {
|
2016-12-03 18:23:47 +09:00
|
|
|
if (!clipBox.Contains(box) || !std::isfinite(box.min.x) ||
|
|
|
|
!std::isfinite(box.min.y) || !std::isfinite(box.min.z) ||
|
|
|
|
!std::isfinite(box.max.x) || !std::isfinite(box.max.y) ||
|
|
|
|
!std::isfinite(box.max.z)) {
|
2015-01-23 18:26:00 +09:00
|
|
|
OnProhibitedAction();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
protected:
|
2016-12-03 18:23:47 +09:00
|
|
|
~SandboxedRenderer() {}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
public:
|
|
|
|
SandboxedRenderer(IRenderer *base) : base(base) {}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void SetClipBox(const AABB3 &b) { clipBox = b; }
|
|
|
|
void SetAllowDepthHack(bool h) { allowDepthHack = h; }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
void Init() { OnProhibitedAction(); }
|
|
|
|
void Shutdown() { OnProhibitedAction(); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
IImage *RegisterImage(const char *filename) { return base->RegisterImage(filename); }
|
|
|
|
IModel *RegisterModel(const char *filename) { return base->RegisterModel(filename); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
IImage *CreateImage(Bitmap *bmp) { return base->CreateImage(bmp); }
|
|
|
|
IModel *CreateModel(VoxelModel *m) { return base->CreateModel(m); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void SetGameMap(GameMap *) { OnProhibitedAction(); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void SetFogDistance(float) { OnProhibitedAction(); }
|
|
|
|
void SetFogColor(Vector3) { OnProhibitedAction(); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void StartScene(const SceneDefinition &) { OnProhibitedAction(); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void AddLight(const client::DynamicLightParam &light) {
|
2015-01-23 18:26:00 +09:00
|
|
|
Vector3 rad(light.radius, light.radius, light.radius);
|
|
|
|
if (CheckVisibility(AABB3(light.origin - rad, light.origin + rad))) {
|
|
|
|
base->AddLight(light);
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-05-25 12:18:32 +09:00
|
|
|
void RenderModel(IModel *model, const ModelRenderParam &_p) {
|
|
|
|
ModelRenderParam p = _p;
|
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
if (!model) {
|
|
|
|
SPInvalidArgument("model");
|
|
|
|
return;
|
|
|
|
}
|
2019-05-25 12:18:32 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
if (p.depthHack && !allowDepthHack) {
|
|
|
|
OnProhibitedAction();
|
|
|
|
return;
|
|
|
|
}
|
2019-05-25 12:18:32 +09:00
|
|
|
|
|
|
|
// Overbright surfaces bypass the fog
|
|
|
|
p.customColor.x = std::max(std::min(p.customColor.x, 1.0f), 0.0f);
|
|
|
|
p.customColor.y = std::max(std::min(p.customColor.y, 1.0f), 0.0f);
|
|
|
|
p.customColor.z = std::max(std::min(p.customColor.z, 1.0f), 0.0f);
|
|
|
|
|
|
|
|
// NaN values bypass the fog
|
|
|
|
if (std::isnan(p.customColor.x) || std::isnan(p.customColor.y) ||
|
|
|
|
std::isnan(p.customColor.z)) {
|
|
|
|
OnProhibitedAction();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
auto bounds = (p.matrix * OBB3(model->GetBoundingBox())).GetBoundingAABB();
|
|
|
|
if (CheckVisibility(bounds)) {
|
|
|
|
base->RenderModel(model, p);
|
|
|
|
}
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
void AddDebugLine(Vector3 a, Vector3 b, Vector4 color) { OnProhibitedAction(); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
void AddSprite(IImage *image, Vector3 center, float radius, float rotation) {
|
|
|
|
Vector3 rad(radius * 1.5f, radius * 1.5f, radius * 1.5f);
|
|
|
|
if (CheckVisibility(AABB3(center - rad, center + rad))) {
|
|
|
|
base->AddSprite(image, center, radius, rotation);
|
|
|
|
}
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
void AddLongSprite(IImage *image, Vector3 p1, Vector3 p2, float radius) {
|
2015-01-23 18:26:00 +09:00
|
|
|
Vector3 rad(radius * 1.5f, radius * 1.5f, radius * 1.5f);
|
|
|
|
AABB3 bounds1(p1 - rad, p1 + rad);
|
|
|
|
AABB3 bounds2(p2 - rad, p2 + rad);
|
|
|
|
bounds1 += bounds2;
|
|
|
|
if (CheckVisibility(bounds1)) {
|
|
|
|
base->AddLongSprite(image, p1, p2, radius);
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
void EndScene() { OnProhibitedAction(); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
void MultiplyScreenColor(Vector3) { OnProhibitedAction(); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
/** Sets color for image drawing. Deprecated because
|
|
|
|
* some methods treats this as an alpha premultiplied, while
|
|
|
|
* others treats this as an alpha non-premultiplied.
|
|
|
|
* @deprecated */
|
2016-12-03 18:23:47 +09:00
|
|
|
void SetColor(Vector4 col) { base->SetColor(col); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
/** Sets color for image drawing. Always alpha premultiplied. */
|
2016-12-03 18:23:47 +09:00
|
|
|
void SetColorAlphaPremultiplied(Vector4 col) { base->SetColorAlphaPremultiplied(col); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void DrawImage(IImage *img, const Vector2 &outTopLeft) {
|
2015-01-24 12:44:57 +09:00
|
|
|
if (allowDepthHack)
|
|
|
|
base->DrawImage(img, outTopLeft);
|
|
|
|
else
|
|
|
|
OnProhibitedAction();
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
void DrawImage(IImage *img, const AABB2 &outRect) {
|
2015-01-24 12:44:57 +09:00
|
|
|
if (allowDepthHack)
|
|
|
|
base->DrawImage(img, outRect);
|
|
|
|
else
|
|
|
|
OnProhibitedAction();
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
void DrawImage(IImage *img, const Vector2 &outTopLeft, const AABB2 &inRect) {
|
2015-01-24 12:44:57 +09:00
|
|
|
if (allowDepthHack)
|
|
|
|
base->DrawImage(img, outTopLeft, inRect);
|
|
|
|
else
|
|
|
|
OnProhibitedAction();
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
void DrawImage(IImage *img, const AABB2 &outRect, const AABB2 &inRect) {
|
2015-01-24 12:44:57 +09:00
|
|
|
if (allowDepthHack)
|
|
|
|
base->DrawImage(img, outRect, inRect);
|
|
|
|
else
|
|
|
|
OnProhibitedAction();
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
void DrawImage(IImage *img, const Vector2 &outTopLeft, const Vector2 &outTopRight,
|
|
|
|
const Vector2 &outBottomLeft, const AABB2 &inRect) {
|
2015-01-24 12:44:57 +09:00
|
|
|
if (allowDepthHack)
|
|
|
|
base->DrawImage(img, outTopLeft, outTopRight, outBottomLeft, inRect);
|
|
|
|
else
|
|
|
|
OnProhibitedAction();
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void DrawFlatGameMap(const AABB2 &outRect, const AABB2 &inRect) {
|
|
|
|
OnProhibitedAction();
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void FrameDone() { OnProhibitedAction(); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void Flip() { OnProhibitedAction(); }
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
Bitmap *ReadBitmap() {
|
|
|
|
OnProhibitedAction();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
float ScreenWidth() { return base->ScreenWidth(); }
|
|
|
|
float ScreenHeight() { return base->ScreenHeight(); }
|
|
|
|
};
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
ClientPlayer::ClientPlayer(Player &p, Client &c)
|
|
|
|
: client(c), player(p), hasValidOriginMatrix(false) {
|
2013-09-21 04:17:34 +09:00
|
|
|
SPADES_MARK_FUNCTION();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
sprintState = 0.f;
|
|
|
|
aimDownState = 0.f;
|
|
|
|
toolRaiseState = 0.f;
|
2019-07-17 00:31:00 +09:00
|
|
|
currentTool = p.GetTool();
|
2013-09-21 04:17:34 +09:00
|
|
|
localFireVibrationTime = -100.f;
|
|
|
|
time = 0.f;
|
|
|
|
viewWeaponOffset = MakeVector3(0, 0, 0);
|
2016-11-22 01:16:28 +09:00
|
|
|
lastFront = MakeVector3(0, 0, 0);
|
2019-07-17 00:31:00 +09:00
|
|
|
flashlightOrientation = p.GetFront();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
ScriptContextHandle ctx;
|
2019-07-17 00:31:00 +09:00
|
|
|
IRenderer *renderer = client.GetRenderer();
|
|
|
|
IAudioDevice *audio = client.GetAudioDevice();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
sandboxedRenderer.Set(new SandboxedRenderer(renderer), false);
|
|
|
|
renderer = sandboxedRenderer;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
static ScriptFunction spadeFactory(
|
|
|
|
"ISpadeSkin@ CreateThirdPersonSpadeSkin(Renderer@, AudioDevice@)");
|
|
|
|
spadeSkin = initScriptFactory(spadeFactory, renderer, audio);
|
|
|
|
|
|
|
|
static ScriptFunction spadeViewFactory(
|
|
|
|
"ISpadeSkin@ CreateViewSpadeSkin(Renderer@, AudioDevice@)");
|
|
|
|
spadeViewSkin = initScriptFactory(spadeViewFactory, renderer, audio);
|
|
|
|
|
|
|
|
static ScriptFunction blockFactory(
|
|
|
|
"IBlockSkin@ CreateThirdPersonBlockSkin(Renderer@, AudioDevice@)");
|
|
|
|
blockSkin = initScriptFactory(blockFactory, renderer, audio);
|
|
|
|
|
|
|
|
static ScriptFunction blockViewFactory(
|
|
|
|
"IBlockSkin@ CreateViewBlockSkin(Renderer@, AudioDevice@)");
|
|
|
|
blockViewSkin = initScriptFactory(blockViewFactory, renderer, audio);
|
|
|
|
|
|
|
|
static ScriptFunction grenadeFactory(
|
|
|
|
"IGrenadeSkin@ CreateThirdPersonGrenadeSkin(Renderer@, AudioDevice@)");
|
|
|
|
grenadeSkin = initScriptFactory(grenadeFactory, renderer, audio);
|
|
|
|
|
|
|
|
static ScriptFunction grenadeViewFactory(
|
|
|
|
"IGrenadeSkin@ CreateViewGrenadeSkin(Renderer@, AudioDevice@)");
|
|
|
|
grenadeViewSkin = initScriptFactory(grenadeViewFactory, renderer, audio);
|
|
|
|
|
|
|
|
static ScriptFunction rifleFactory(
|
|
|
|
"IWeaponSkin@ CreateThirdPersonRifleSkin(Renderer@, AudioDevice@)");
|
|
|
|
static ScriptFunction smgFactory(
|
|
|
|
"IWeaponSkin@ CreateThirdPersonSMGSkin(Renderer@, AudioDevice@)");
|
|
|
|
static ScriptFunction shotgunFactory(
|
|
|
|
"IWeaponSkin@ CreateThirdPersonShotgunSkin(Renderer@, AudioDevice@)");
|
|
|
|
static ScriptFunction rifleViewFactory(
|
|
|
|
"IWeaponSkin@ CreateViewRifleSkin(Renderer@, AudioDevice@)");
|
|
|
|
static ScriptFunction smgViewFactory(
|
|
|
|
"IWeaponSkin@ CreateViewSMGSkin(Renderer@, AudioDevice@)");
|
|
|
|
static ScriptFunction shotgunViewFactory(
|
|
|
|
"IWeaponSkin@ CreateViewShotgunSkin(Renderer@, AudioDevice@)");
|
2019-07-17 00:31:00 +09:00
|
|
|
switch (p.GetWeapon().GetWeaponType()) {
|
2013-09-21 04:17:34 +09:00
|
|
|
case RIFLE_WEAPON:
|
2016-12-03 18:23:47 +09:00
|
|
|
weaponSkin = initScriptFactory(rifleFactory, renderer, audio);
|
|
|
|
weaponViewSkin = initScriptFactory(rifleViewFactory, renderer, audio);
|
2013-09-21 04:17:34 +09:00
|
|
|
break;
|
|
|
|
case SMG_WEAPON:
|
2016-12-03 18:23:47 +09:00
|
|
|
weaponSkin = initScriptFactory(smgFactory, renderer, audio);
|
|
|
|
weaponViewSkin = initScriptFactory(smgViewFactory, renderer, audio);
|
2013-09-21 04:17:34 +09:00
|
|
|
break;
|
|
|
|
case SHOTGUN_WEAPON:
|
2016-12-03 18:23:47 +09:00
|
|
|
weaponSkin = initScriptFactory(shotgunFactory, renderer, audio);
|
|
|
|
weaponViewSkin = initScriptFactory(shotgunViewFactory, renderer, audio);
|
2013-09-21 04:17:34 +09:00
|
|
|
break;
|
2016-12-03 18:23:47 +09:00
|
|
|
default: SPAssert(false);
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ClientPlayer::~ClientPlayer() {
|
|
|
|
spadeSkin->Release();
|
|
|
|
blockSkin->Release();
|
|
|
|
weaponSkin->Release();
|
|
|
|
grenadeSkin->Release();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
spadeViewSkin->Release();
|
|
|
|
blockViewSkin->Release();
|
|
|
|
weaponViewSkin->Release();
|
|
|
|
grenadeViewSkin->Release();
|
|
|
|
}
|
2013-11-03 17:13:49 +01:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
asIScriptObject *ClientPlayer::initScriptFactory(ScriptFunction &creator,
|
|
|
|
IRenderer *renderer, IAudioDevice *audio) {
|
2013-11-03 17:13:49 +01:00
|
|
|
ScriptContextHandle ctx = creator.Prepare();
|
2016-12-03 18:23:47 +09:00
|
|
|
ctx->SetArgObject(0, reinterpret_cast<void *>(renderer));
|
|
|
|
ctx->SetArgObject(1, reinterpret_cast<void *>(audio));
|
2013-11-03 17:13:49 +01:00
|
|
|
ctx.ExecuteChecked();
|
2016-12-03 18:23:47 +09:00
|
|
|
asIScriptObject *result = reinterpret_cast<asIScriptObject *>(ctx->GetReturnObject());
|
2013-11-03 17:13:49 +01:00
|
|
|
result->AddRef();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
bool ClientPlayer::IsChangingTool() {
|
2019-07-17 00:31:00 +09:00
|
|
|
return currentTool != player.GetTool() || toolRaiseState < .999f;
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
float ClientPlayer::GetLocalFireVibration() {
|
|
|
|
float localFireVibration = 0.f;
|
|
|
|
localFireVibration = time - localFireVibrationTime;
|
|
|
|
localFireVibration = 1.f - localFireVibration / 0.1f;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (localFireVibration < 0.f)
|
2013-09-21 04:17:34 +09:00
|
|
|
localFireVibration = 0.f;
|
|
|
|
return localFireVibration;
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
void ClientPlayer::Update(float dt) {
|
|
|
|
time += dt;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
PlayerInput actualInput = player.GetInput();
|
|
|
|
WeaponInput actualWeapInput = player.GetWeaponInput();
|
|
|
|
if (actualInput.sprint && player.IsAlive()) {
|
2013-09-21 04:17:34 +09:00
|
|
|
sprintState += dt * 4.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (sprintState > 1.f)
|
2013-09-21 04:17:34 +09:00
|
|
|
sprintState = 1.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
sprintState -= dt * 3.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (sprintState < 0.f)
|
2013-09-21 04:17:34 +09:00
|
|
|
sprintState = 0.f;
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
if (actualWeapInput.secondary && player.IsToolWeapon() && player.IsAlive()) {
|
2016-11-20 19:13:00 +09:00
|
|
|
// This is the only animation that can be turned off
|
|
|
|
// here; others affect the gameplay directly and
|
|
|
|
// turning them off would be considered cheating
|
|
|
|
if (cg_animations) {
|
|
|
|
aimDownState += dt * 8.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (aimDownState > 1.f)
|
2016-11-20 19:13:00 +09:00
|
|
|
aimDownState = 1.f;
|
|
|
|
} else {
|
|
|
|
aimDownState = 1.f;
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2016-11-20 19:13:00 +09:00
|
|
|
if (cg_animations) {
|
|
|
|
aimDownState -= dt * 3.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (aimDownState < 0.f)
|
2016-11-20 19:13:00 +09:00
|
|
|
aimDownState = 0.f;
|
|
|
|
} else {
|
|
|
|
aimDownState = 0.f;
|
|
|
|
}
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
if (currentTool == player.GetTool()) {
|
2013-09-21 04:17:34 +09:00
|
|
|
toolRaiseState += dt * 4.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (toolRaiseState > 1.f)
|
2013-09-21 04:17:34 +09:00
|
|
|
toolRaiseState = 1.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (toolRaiseState < 0.f)
|
2013-09-21 04:17:34 +09:00
|
|
|
toolRaiseState = 0.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
toolRaiseState -= dt * 4.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (toolRaiseState < 0.f) {
|
2013-09-21 04:17:34 +09:00
|
|
|
toolRaiseState = 0.f;
|
2019-07-17 00:31:00 +09:00
|
|
|
currentTool = player.GetTool();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2014-03-22 01:37:14 +09:00
|
|
|
// play tool change sound
|
2019-07-17 00:31:00 +09:00
|
|
|
if (player.IsLocalPlayer()) {
|
|
|
|
auto *audioDevice = client.GetAudioDevice();
|
2014-03-22 01:37:14 +09:00
|
|
|
Handle<IAudioChunk> c;
|
2019-07-17 00:31:00 +09:00
|
|
|
switch (player.GetTool()) {
|
2014-03-22 01:37:14 +09:00
|
|
|
case Player::ToolSpade:
|
2017-01-06 04:01:10 +09:00
|
|
|
c = audioDevice->RegisterSound(
|
|
|
|
"Sounds/Weapons/Spade/RaiseLocal.opus");
|
2014-03-22 01:37:14 +09:00
|
|
|
break;
|
|
|
|
case Player::ToolBlock:
|
2017-01-06 04:01:10 +09:00
|
|
|
c = audioDevice->RegisterSound(
|
|
|
|
"Sounds/Weapons/Block/RaiseLocal.opus");
|
2014-03-22 01:37:14 +09:00
|
|
|
break;
|
|
|
|
case Player::ToolWeapon:
|
2019-07-17 00:31:00 +09:00
|
|
|
switch (player.GetWeapon().GetWeaponType()) {
|
2014-03-22 01:37:14 +09:00
|
|
|
case RIFLE_WEAPON:
|
2016-12-03 18:23:47 +09:00
|
|
|
c = audioDevice->RegisterSound(
|
2016-12-18 00:45:17 +09:00
|
|
|
"Sounds/Weapons/Rifle/RaiseLocal.opus");
|
2014-03-22 01:37:14 +09:00
|
|
|
break;
|
|
|
|
case SMG_WEAPON:
|
2016-12-03 18:23:47 +09:00
|
|
|
c = audioDevice->RegisterSound(
|
2016-12-18 00:45:17 +09:00
|
|
|
"Sounds/Weapons/SMG/RaiseLocal.opus");
|
2014-03-22 01:37:14 +09:00
|
|
|
break;
|
|
|
|
case SHOTGUN_WEAPON:
|
2016-12-03 18:23:47 +09:00
|
|
|
c = audioDevice->RegisterSound(
|
2016-12-18 00:45:17 +09:00
|
|
|
"Sounds/Weapons/Shotgun/RaiseLocal.opus");
|
2014-03-22 01:37:14 +09:00
|
|
|
break;
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2014-03-22 01:37:14 +09:00
|
|
|
break;
|
|
|
|
case Player::ToolGrenade:
|
2016-12-03 18:23:47 +09:00
|
|
|
c = audioDevice->RegisterSound(
|
2016-12-18 00:45:17 +09:00
|
|
|
"Sounds/Weapons/Grenade/RaiseLocal.opus");
|
2014-03-22 01:37:14 +09:00
|
|
|
break;
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam());
|
2014-03-22 01:37:14 +09:00
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (toolRaiseState > 1.f) {
|
2013-09-21 04:17:34 +09:00
|
|
|
toolRaiseState = 1.f;
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
{
|
|
|
|
float scale = dt;
|
2019-07-17 00:31:00 +09:00
|
|
|
Vector3 vel = player.GetVelocty();
|
|
|
|
Vector3 front = player.GetFront();
|
|
|
|
Vector3 right = player.GetRight();
|
|
|
|
Vector3 up = player.GetUp();
|
2016-11-22 01:16:28 +09:00
|
|
|
|
|
|
|
// Offset the view weapon according to the player movement
|
2013-09-21 04:17:34 +09:00
|
|
|
viewWeaponOffset.x += Vector3::Dot(vel, right) * scale;
|
|
|
|
viewWeaponOffset.y -= Vector3::Dot(vel, front) * scale;
|
|
|
|
viewWeaponOffset.z += Vector3::Dot(vel, up) * scale;
|
2016-11-22 01:16:28 +09:00
|
|
|
|
|
|
|
// Offset the view weapon according to the camera movement
|
|
|
|
Vector3 diff = front - lastFront;
|
|
|
|
viewWeaponOffset.x += Vector3::Dot(diff, right) * 0.05f;
|
|
|
|
viewWeaponOffset.z += Vector3::Dot(diff, up) * 0.05f;
|
|
|
|
|
|
|
|
lastFront = front;
|
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (dt > 0.f)
|
2013-09-21 04:17:34 +09:00
|
|
|
viewWeaponOffset *= powf(.02f, dt);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-11-22 01:16:28 +09:00
|
|
|
// Limit the movement
|
2016-12-03 18:23:47 +09:00
|
|
|
auto softLimitFunc = [&](float &v, float minLimit, float maxLimit) {
|
2016-11-22 01:16:28 +09:00
|
|
|
float transition = (maxLimit - minLimit) * 0.5f;
|
|
|
|
if (v < minLimit) {
|
|
|
|
float strength = std::min(1.f, (minLimit - v) / transition);
|
|
|
|
v = Mix(v, minLimit, strength);
|
|
|
|
}
|
|
|
|
if (v > maxLimit) {
|
|
|
|
float strength = std::min(1.f, (v - maxLimit) / transition);
|
|
|
|
v = Mix(v, maxLimit, strength);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
softLimitFunc(viewWeaponOffset.x, -0.06f, 0.06f);
|
|
|
|
softLimitFunc(viewWeaponOffset.y, -0.06f, 0.06f);
|
|
|
|
softLimitFunc(viewWeaponOffset.z, -0.06f, 0.06f);
|
|
|
|
|
|
|
|
// When the player is aiming down the sight, the weapon's movement
|
|
|
|
// must be restricted so that other parts of the weapon don't
|
|
|
|
// cover the ironsight.
|
2019-07-17 00:31:00 +09:00
|
|
|
if (currentTool == Player::ToolWeapon && player.GetWeaponInput().secondary) {
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (dt > 0.f)
|
2013-09-21 04:17:34 +09:00
|
|
|
viewWeaponOffset *= powf(.01f, dt);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-17 22:48:16 +09:00
|
|
|
const float limitX = .003f;
|
|
|
|
const float limitY = .003f;
|
2016-11-22 01:16:28 +09:00
|
|
|
softLimitFunc(viewWeaponOffset.x, -limitX, limitX);
|
|
|
|
softLimitFunc(viewWeaponOffset.z, 0, limitY);
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-05-05 23:32:57 +09:00
|
|
|
{
|
|
|
|
// Smooth the flashlight's movement
|
2019-07-17 00:31:00 +09:00
|
|
|
Vector3 diff = player.GetFront() - flashlightOrientation;
|
2019-05-05 23:32:57 +09:00
|
|
|
float sq = diff.GetLength();
|
|
|
|
if (sq > 0.1) {
|
|
|
|
flashlightOrientation += diff.Normalize() * (sq - 0.1);
|
|
|
|
}
|
|
|
|
|
|
|
|
flashlightOrientation =
|
2019-07-17 00:31:00 +09:00
|
|
|
Mix(flashlightOrientation, player.GetFront(), 1.0f - powf(1.0e-6, dt))
|
2019-05-05 23:32:57 +09:00
|
|
|
.Normalize();
|
|
|
|
}
|
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// FIXME: should do for non-active skins?
|
|
|
|
asIScriptObject *skin;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (ShouldRenderInThirdPersonView()) {
|
|
|
|
if (currentTool == Player::ToolSpade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = spadeSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolBlock) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = blockSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolGrenade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = grenadeSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolWeapon) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = weaponSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
SPInvalidEnum("currentTool", currentTool);
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
|
|
|
if (currentTool == Player::ToolSpade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = spadeViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolBlock) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = blockViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolGrenade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = grenadeViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolWeapon) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = weaponViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
SPInvalidEnum("currentTool", currentTool);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
ScriptIToolSkin interface(skin);
|
|
|
|
interface.Update(dt);
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
Matrix4 ClientPlayer::GetEyeMatrix() {
|
2019-07-17 00:31:00 +09:00
|
|
|
Vector3 eye = player.GetEye();
|
2016-11-22 01:16:28 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if ((int)cg_shake >= 2) {
|
2016-11-22 01:16:28 +09:00
|
|
|
float sp = SmoothStep(GetSprintState());
|
2016-12-03 18:23:47 +09:00
|
|
|
float p =
|
2019-07-17 00:31:00 +09:00
|
|
|
cosf(player.GetWalkAnimationProgress() * static_cast<float>(M_PI) * 2.f - 0.8f);
|
2016-12-03 18:23:47 +09:00
|
|
|
p = p * p;
|
|
|
|
p *= p;
|
|
|
|
p *= p;
|
|
|
|
p *= p;
|
2016-11-22 01:16:28 +09:00
|
|
|
eye.z -= p * 0.06f * sp;
|
|
|
|
}
|
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
return Matrix4::FromAxis(-player.GetRight(), player.GetFront(), -player.GetUp(),
|
2016-12-03 18:23:47 +09:00
|
|
|
eye);
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void ClientPlayer::SetSkinParameterForTool(Player::ToolType type, asIScriptObject *skin) {
|
2019-07-17 00:31:00 +09:00
|
|
|
Player &p = player;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (currentTool == Player::ToolSpade) {
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
ScriptISpadeSkin interface(skin);
|
2019-07-17 00:31:00 +09:00
|
|
|
WeaponInput inp = p.GetWeaponInput();
|
|
|
|
if (p.GetTool() != Player::ToolSpade) {
|
2013-09-23 02:10:47 +09:00
|
|
|
interface.SetActionType(SpadeActionTypeIdle);
|
|
|
|
interface.SetActionProgress(0.f);
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (inp.primary) {
|
2013-09-21 04:17:34 +09:00
|
|
|
interface.SetActionType(SpadeActionTypeBash);
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetActionProgress(p.GetSpadeAnimationProgress());
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (inp.secondary) {
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetActionType(p.IsFirstDig() ? SpadeActionTypeDigStart
|
2016-12-03 18:23:47 +09:00
|
|
|
: SpadeActionTypeDig);
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetActionProgress(p.GetDigAnimationProgress());
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
interface.SetActionType(SpadeActionTypeIdle);
|
|
|
|
interface.SetActionProgress(0.f);
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolBlock) {
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// TODO: smooth ready state
|
|
|
|
ScriptIBlockSkin interface(skin);
|
2019-07-17 00:31:00 +09:00
|
|
|
if (p.GetTool() != Player::ToolBlock) {
|
2013-09-23 02:10:47 +09:00
|
|
|
// FIXME: use block's IsReadyToUseTool
|
|
|
|
// for smoother transition
|
|
|
|
interface.SetReadyState(0.f);
|
2019-07-17 00:31:00 +09:00
|
|
|
} else if (p.IsReadyToUseTool()) {
|
2013-09-21 04:17:34 +09:00
|
|
|
interface.SetReadyState(1.f);
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
interface.SetReadyState(0.f);
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetBlockColor(MakeVector3(p.GetBlockColor()) / 255.f);
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolGrenade) {
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
ScriptIGrenadeSkin interface(skin);
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetReadyState(1.f - p.GetTimeToNextGrenade() / 0.5f);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
WeaponInput inp = p.GetWeaponInput();
|
2016-12-03 18:23:47 +09:00
|
|
|
if (inp.primary) {
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetCookTime(p.GetGrenadeCookTime());
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
interface.SetCookTime(0.f);
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolWeapon) {
|
2019-07-17 00:31:00 +09:00
|
|
|
Weapon &w = p.GetWeapon();
|
2013-09-21 04:17:34 +09:00
|
|
|
ScriptIWeaponSkin interface(skin);
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetReadyState(1.f - w.TimeToNextFire() / w.GetDelay());
|
2013-09-21 04:17:34 +09:00
|
|
|
interface.SetAimDownSightState(aimDownState);
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetAmmo(w.GetAmmo());
|
|
|
|
interface.SetClipSize(w.GetClipSize());
|
|
|
|
interface.SetReloading(w.IsReloading());
|
|
|
|
interface.SetReloadProgress(w.GetReloadProgress());
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
SPInvalidEnum("currentTool", currentTool);
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void ClientPlayer::SetCommonSkinParameter(asIScriptObject *skin) {
|
2013-09-21 04:17:34 +09:00
|
|
|
asIScriptObject *curSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (ShouldRenderInThirdPersonView()) {
|
|
|
|
if (currentTool == Player::ToolSpade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
curSkin = spadeSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolBlock) {
|
2013-09-21 04:17:34 +09:00
|
|
|
curSkin = blockSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolGrenade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
curSkin = grenadeSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolWeapon) {
|
2013-09-21 04:17:34 +09:00
|
|
|
curSkin = weaponSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
SPInvalidEnum("currentTool", currentTool);
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
|
|
|
if (currentTool == Player::ToolSpade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
curSkin = spadeViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolBlock) {
|
2013-09-21 04:17:34 +09:00
|
|
|
curSkin = blockViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolGrenade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
curSkin = grenadeViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolWeapon) {
|
2013-09-21 04:17:34 +09:00
|
|
|
curSkin = weaponViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
SPInvalidEnum("currentTool", currentTool);
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
float sprint = SmoothStep(sprintState);
|
|
|
|
float putdown = 1.f - toolRaiseState;
|
|
|
|
putdown *= putdown;
|
|
|
|
putdown = std::min(1.f, putdown * 1.5f);
|
|
|
|
{
|
|
|
|
ScriptIToolSkin interface(skin);
|
2016-12-03 18:23:47 +09:00
|
|
|
interface.SetRaiseState((skin == curSkin) ? (1.f - putdown) : 0.f);
|
2013-09-21 04:17:34 +09:00
|
|
|
interface.SetSprintState(sprint);
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetMuted(client.IsMuted());
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-05-05 23:32:57 +09:00
|
|
|
std::array<Vector3, 3> ClientPlayer::GetFlashlightAxes() {
|
|
|
|
std::array<Vector3, 3> axes;
|
|
|
|
|
|
|
|
axes[2] = flashlightOrientation;
|
2019-07-17 00:31:00 +09:00
|
|
|
axes[0] = Vector3::Cross(flashlightOrientation, player.GetUp()).Normalize();
|
2019-05-05 23:32:57 +09:00
|
|
|
axes[1] = Vector3::Cross(axes[0], axes[2]);
|
|
|
|
|
|
|
|
return axes;
|
|
|
|
}
|
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
void ClientPlayer::AddToSceneFirstPersonView() {
|
2019-07-17 00:31:00 +09:00
|
|
|
Player &p = player;
|
|
|
|
IRenderer *renderer = client.GetRenderer();
|
|
|
|
World *world = client.GetWorld();
|
2013-09-21 04:17:34 +09:00
|
|
|
Matrix4 eyeMatrix = GetEyeMatrix();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2015-01-23 18:26:00 +09:00
|
|
|
sandboxedRenderer->SetClipBox(AABB3(eyeMatrix.GetOrigin() - Vector3(20.f, 20.f, 20.f),
|
2016-12-03 18:23:47 +09:00
|
|
|
eyeMatrix.GetOrigin() + Vector3(20.f, 20.f, 20.f)));
|
2015-01-23 18:26:00 +09:00
|
|
|
sandboxedRenderer->SetAllowDepthHack(true);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2018-07-15 16:07:34 -03:00
|
|
|
// no flashlight if spectating other players while dead
|
2019-07-17 00:31:00 +09:00
|
|
|
if (client.flashlightOn && world->GetLocalPlayer()->IsAlive()) {
|
2013-09-21 04:17:34 +09:00
|
|
|
float brightness;
|
2019-07-17 00:31:00 +09:00
|
|
|
brightness = client.time - client.flashlightOnTime;
|
2013-09-21 04:17:34 +09:00
|
|
|
brightness = 1.f - expf(-brightness * 5.f);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// add flash light
|
|
|
|
DynamicLightParam light;
|
|
|
|
light.origin = (eyeMatrix * MakeVector3(0, -0.05f, -0.1f)).GetXYZ();
|
|
|
|
light.color = MakeVector3(1, .7f, .5f) * 1.5f * brightness;
|
|
|
|
light.radius = 40.f;
|
|
|
|
light.type = DynamicLightTypeSpotlight;
|
|
|
|
light.spotAngle = 30.f * M_PI / 180.f;
|
2019-05-05 23:32:57 +09:00
|
|
|
light.spotAxis = GetFlashlightAxes();
|
2016-07-16 00:14:59 +09:00
|
|
|
light.image = renderer->RegisterImage("Gfx/Spotlight.png");
|
2013-09-21 04:17:34 +09:00
|
|
|
renderer->AddLight(light);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
light.color *= .3f;
|
|
|
|
light.radius = 10.f;
|
|
|
|
light.type = DynamicLightTypePoint;
|
|
|
|
light.image = NULL;
|
|
|
|
renderer->AddLight(light);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// add glare
|
2016-12-03 18:23:47 +09:00
|
|
|
renderer->SetColorAlphaPremultiplied(MakeVector4(1, .7f, .5f, 0) * brightness *
|
|
|
|
.3f);
|
|
|
|
renderer->AddSprite(renderer->RegisterImage("Gfx/Glare.png"),
|
|
|
|
(eyeMatrix * MakeVector3(0, 0.3f, -0.3f)).GetXYZ(), .8f, 0.f);
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
Vector3 leftHand, rightHand;
|
|
|
|
leftHand = MakeVector3(0, 0, 0);
|
|
|
|
rightHand = MakeVector3(0, 0, 0);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// view weapon
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
Vector3 viewWeaponOffset = this->viewWeaponOffset;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// bobbing
|
|
|
|
{
|
|
|
|
float sp = 1.f - aimDownState;
|
|
|
|
sp *= .3f;
|
2019-07-17 00:31:00 +09:00
|
|
|
sp *= std::min(1.f, p.GetVelocty().GetLength() * 5.f);
|
2016-12-03 18:23:47 +09:00
|
|
|
viewWeaponOffset.x +=
|
2019-07-17 00:31:00 +09:00
|
|
|
sinf(p.GetWalkAnimationProgress() * M_PI * 2.f) * 0.013f * sp;
|
|
|
|
float vl = cosf(p.GetWalkAnimationProgress() * M_PI * 2.f);
|
2013-09-21 04:17:34 +09:00
|
|
|
vl *= vl;
|
2016-11-22 01:16:28 +09:00
|
|
|
viewWeaponOffset.z += vl * 0.018f * sp;
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// slow pulse
|
|
|
|
{
|
|
|
|
float sp = 1.f - aimDownState;
|
|
|
|
float vl = sinf(world->GetTime() * 1.f);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
viewWeaponOffset.x += vl * 0.001f * sp;
|
|
|
|
viewWeaponOffset.y += vl * 0.0007f * sp;
|
|
|
|
viewWeaponOffset.z += vl * 0.003f * sp;
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2017-03-04 03:44:57 +09:00
|
|
|
// manual adjustment
|
2019-07-17 00:31:00 +09:00
|
|
|
viewWeaponOffset +=
|
|
|
|
Vector3{cg_viewWeaponX, cg_viewWeaponY, cg_viewWeaponZ} * (1.f - aimDownState);
|
2017-03-04 03:44:57 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
asIScriptObject *skin;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (currentTool == Player::ToolSpade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = spadeViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolBlock) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = blockViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolGrenade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = grenadeViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolWeapon) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = weaponViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
SPInvalidEnum("currentTool", currentTool);
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
SetSkinParameterForTool(currentTool, skin);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
SetCommonSkinParameter(skin);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// common process
|
|
|
|
{
|
|
|
|
ScriptIViewToolSkin interface(skin);
|
|
|
|
interface.SetEyeMatrix(GetEyeMatrix());
|
|
|
|
interface.SetSwing(viewWeaponOffset);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
ScriptIToolSkin interface(skin);
|
|
|
|
interface.AddToScene();
|
|
|
|
}
|
|
|
|
{
|
|
|
|
ScriptIViewToolSkin interface(skin);
|
|
|
|
leftHand = interface.GetLeftHandPosition();
|
|
|
|
rightHand = interface.GetRightHandPosition();
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// view hands
|
2016-12-03 18:23:47 +09:00
|
|
|
if (leftHand.GetPoweredLength() > 0.001f && rightHand.GetPoweredLength() > 0.001f) {
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
ModelRenderParam param;
|
|
|
|
param.depthHack = true;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-03 17:13:49 +01:00
|
|
|
IModel *model = renderer->RegisterModel("Models/Player/Arm.kv6");
|
|
|
|
IModel *model2 = renderer->RegisterModel("Models/Player/UpperArm.kv6");
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
IntVector3 col = p.GetColor();
|
2016-12-03 18:23:47 +09:00
|
|
|
param.customColor = MakeVector3(col.x / 255.f, col.y / 255.f, col.z / 255.f);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
const float armlen = 0.5f;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
Vector3 shoulders[] = {{0.4f, 0.0f, 0.25f}, {-0.4f, 0.0f, 0.25f}};
|
2013-09-21 04:17:34 +09:00
|
|
|
Vector3 hands[] = {leftHand, rightHand};
|
2016-12-03 18:23:47 +09:00
|
|
|
Vector3 benddirs[] = {{0.5f, 0.2f, 0.f}, {-0.5f, 0.2f, 0.f}};
|
|
|
|
for (int i = 0; i < 2; i++) {
|
2013-09-21 04:17:34 +09:00
|
|
|
Vector3 shoulder = shoulders[i];
|
|
|
|
Vector3 hand = hands[i];
|
|
|
|
Vector3 benddir = benddirs[i];
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
float len2 = (hand - shoulder).GetPoweredLength();
|
|
|
|
// len2/4 + x^2 = armlen^2
|
2016-12-03 18:23:47 +09:00
|
|
|
float bendlen = sqrtf(std::max(armlen * armlen - len2 * .25f, 0.f));
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
Vector3 bend = Vector3::Cross(benddir, hand - shoulder);
|
2013-09-21 04:17:34 +09:00
|
|
|
bend = bend.Normalize();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (bend.z < 0.f)
|
|
|
|
bend.z = -bend.z;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
Vector3 elbow = (hand + shoulder) * .5f;
|
|
|
|
elbow += bend * bendlen;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
{
|
|
|
|
Vector3 axises[3];
|
|
|
|
axises[2] = (hand - elbow).Normalize();
|
|
|
|
axises[0] = MakeVector3(0, 0, 1);
|
|
|
|
axises[1] = Vector3::Cross(axises[2], axises[0]).Normalize();
|
|
|
|
axises[0] = Vector3::Cross(axises[1], axises[2]).Normalize();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
Matrix4 mat = Matrix4::Scale(.05f);
|
2013-11-22 23:09:16 +01:00
|
|
|
mat = Matrix4::FromAxis(axises[0], axises[1], axises[2], elbow) * mat;
|
2013-09-21 04:17:34 +09:00
|
|
|
mat = eyeMatrix * mat;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
param.matrix = mat;
|
|
|
|
renderer->RenderModel(model, param);
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
{
|
|
|
|
Vector3 axises[3];
|
|
|
|
axises[2] = (elbow - shoulder).Normalize();
|
|
|
|
axises[0] = MakeVector3(0, 0, 1);
|
|
|
|
axises[1] = Vector3::Cross(axises[2], axises[0]).Normalize();
|
|
|
|
axises[0] = Vector3::Cross(axises[1], axises[2]).Normalize();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
Matrix4 mat = Matrix4::Scale(.05f);
|
2013-11-22 23:09:16 +01:00
|
|
|
mat = Matrix4::FromAxis(axises[0], axises[1], axises[2], shoulder) * mat;
|
2013-09-21 04:17:34 +09:00
|
|
|
mat = eyeMatrix * mat;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
param.matrix = mat;
|
|
|
|
renderer->RenderModel(model2, param);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// --- local view ends
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
void ClientPlayer::AddToSceneThirdPersonView() {
|
2019-07-17 00:31:00 +09:00
|
|
|
Player &p = player;
|
|
|
|
IRenderer *renderer = client.GetRenderer();
|
|
|
|
World *world = client.GetWorld();
|
2013-09-21 04:17:34 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
if (!p.IsAlive()) {
|
2016-12-03 18:23:47 +09:00
|
|
|
if (!cg_ragdoll) {
|
2013-09-21 04:17:34 +09:00
|
|
|
ModelRenderParam param;
|
2019-07-17 00:31:00 +09:00
|
|
|
param.matrix = Matrix4::Translate(p.GetOrigin() + MakeVector3(0, 0, 1));
|
2013-09-21 04:17:34 +09:00
|
|
|
param.matrix = param.matrix * Matrix4::Scale(.1f);
|
2019-07-17 00:31:00 +09:00
|
|
|
IntVector3 col = p.GetColor();
|
2016-12-03 18:23:47 +09:00
|
|
|
param.customColor = MakeVector3(col.x / 255.f, col.y / 255.f, col.z / 255.f);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
IModel *model = renderer->RegisterModel("Models/Player/Dead.kv6");
|
|
|
|
renderer->RenderModel(model, param);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
auto origin = p.GetOrigin();
|
2016-12-03 18:23:47 +09:00
|
|
|
sandboxedRenderer->SetClipBox(
|
|
|
|
AABB3(origin - Vector3(2.f, 2.f, 4.f), origin + Vector3(2.f, 2.f, 2.f)));
|
2015-01-23 18:26:00 +09:00
|
|
|
sandboxedRenderer->SetAllowDepthHack(false);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// ready for tool rendering
|
|
|
|
asIScriptObject *skin;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (currentTool == Player::ToolSpade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = spadeSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolBlock) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = blockSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolGrenade) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = grenadeSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolWeapon) {
|
2013-09-21 04:17:34 +09:00
|
|
|
skin = weaponSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
SPInvalidEnum("currentTool", currentTool);
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
SetSkinParameterForTool(currentTool, skin);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
SetCommonSkinParameter(skin);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
float pitchBias;
|
|
|
|
{
|
|
|
|
ScriptIThirdPersonToolSkin interface(skin);
|
|
|
|
pitchBias = interface.GetPitchBias();
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
ModelRenderParam param;
|
|
|
|
IModel *model;
|
2019-07-17 00:31:00 +09:00
|
|
|
Vector3 front = p.GetFront();
|
|
|
|
IntVector3 col = p.GetColor();
|
2016-12-03 18:23:47 +09:00
|
|
|
param.customColor = MakeVector3(col.x / 255.f, col.y / 255.f, col.z / 255.f);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
float yaw = atan2(front.y, front.x) + M_PI * .5f;
|
|
|
|
float pitch = -atan2(front.z, sqrt(front.x * front.x + front.y * front.y));
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// lower axis
|
2019-07-17 00:31:00 +09:00
|
|
|
Matrix4 lower = Matrix4::Translate(p.GetOrigin());
|
2016-12-03 18:23:47 +09:00
|
|
|
lower = lower * Matrix4::Rotate(MakeVector3(0, 0, 1), yaw);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
Matrix4 scaler = Matrix4::Scale(0.1f);
|
2016-12-03 18:23:47 +09:00
|
|
|
scaler = scaler * Matrix4::Scale(-1, -1, 1);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
PlayerInput inp = p.GetInput();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// lower
|
|
|
|
Matrix4 torso, head, arms;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (inp.crouch) {
|
2013-09-21 04:17:34 +09:00
|
|
|
Matrix4 leg1 = Matrix4::Translate(-0.25f, 0.2f, -0.1f);
|
2016-12-03 18:23:47 +09:00
|
|
|
Matrix4 leg2 = Matrix4::Translate(0.25f, 0.2f, -0.1f);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
float ang = sinf(p.GetWalkAnimationProgress() * M_PI * 2.f) * 0.6f;
|
|
|
|
float walkVel = Vector3::Dot(p.GetVelocty(), p.GetFront2D()) * 4.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
leg1 = leg1 * Matrix4::Rotate(MakeVector3(1, 0, 0), ang * walkVel);
|
|
|
|
leg2 = leg2 * Matrix4::Rotate(MakeVector3(1, 0, 0), -ang * walkVel);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
walkVel = Vector3::Dot(p.GetVelocty(), p.GetRight()) * 3.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
leg1 = leg1 * Matrix4::Rotate(MakeVector3(0, 1, 0), ang * walkVel);
|
|
|
|
leg2 = leg2 * Matrix4::Rotate(MakeVector3(0, 1, 0), -ang * walkVel);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
leg1 = lower * leg1;
|
|
|
|
leg2 = lower * leg2;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-03 17:13:49 +01:00
|
|
|
model = renderer->RegisterModel("Models/Player/LegCrouch.kv6");
|
2013-09-21 04:17:34 +09:00
|
|
|
param.matrix = leg1 * scaler;
|
|
|
|
renderer->RenderModel(model, param);
|
|
|
|
param.matrix = leg2 * scaler;
|
|
|
|
renderer->RenderModel(model, param);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
torso = Matrix4::Translate(0.f, 0.f, -0.55f);
|
2013-09-21 04:17:34 +09:00
|
|
|
torso = lower * torso;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-03 17:13:49 +01:00
|
|
|
model = renderer->RegisterModel("Models/Player/TorsoCrouch.kv6");
|
2013-09-21 04:17:34 +09:00
|
|
|
param.matrix = torso * scaler;
|
|
|
|
renderer->RenderModel(model, param);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
head = Matrix4::Translate(0.f, 0.f, -0.0f);
|
2013-09-21 04:17:34 +09:00
|
|
|
head = torso * head;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
arms = Matrix4::Translate(0.f, 0.f, -0.0f);
|
2013-09-21 04:17:34 +09:00
|
|
|
arms = torso * arms;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-21 04:17:34 +09:00
|
|
|
Matrix4 leg1 = Matrix4::Translate(-0.25f, 0.f, -0.1f);
|
2016-12-03 18:23:47 +09:00
|
|
|
Matrix4 leg2 = Matrix4::Translate(0.25f, 0.f, -0.1f);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
float ang = sinf(p.GetWalkAnimationProgress() * M_PI * 2.f) * 0.6f;
|
|
|
|
float walkVel = Vector3::Dot(p.GetVelocty(), p.GetFront2D()) * 4.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
leg1 = leg1 * Matrix4::Rotate(MakeVector3(1, 0, 0), ang * walkVel);
|
|
|
|
leg2 = leg2 * Matrix4::Rotate(MakeVector3(1, 0, 0), -ang * walkVel);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
walkVel = Vector3::Dot(p.GetVelocty(), p.GetRight()) * 3.f;
|
2016-12-03 18:23:47 +09:00
|
|
|
leg1 = leg1 * Matrix4::Rotate(MakeVector3(0, 1, 0), ang * walkVel);
|
|
|
|
leg2 = leg2 * Matrix4::Rotate(MakeVector3(0, 1, 0), -ang * walkVel);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
leg1 = lower * leg1;
|
|
|
|
leg2 = lower * leg2;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-03 17:13:49 +01:00
|
|
|
model = renderer->RegisterModel("Models/Player/Leg.kv6");
|
2013-09-21 04:17:34 +09:00
|
|
|
param.matrix = leg1 * scaler;
|
|
|
|
renderer->RenderModel(model, param);
|
|
|
|
param.matrix = leg2 * scaler;
|
|
|
|
renderer->RenderModel(model, param);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
torso = Matrix4::Translate(0.f, 0.f, -1.0f);
|
2013-09-21 04:17:34 +09:00
|
|
|
torso = lower * torso;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-03 17:13:49 +01:00
|
|
|
model = renderer->RegisterModel("Models/Player/Torso.kv6");
|
2013-09-21 04:17:34 +09:00
|
|
|
param.matrix = torso * scaler;
|
|
|
|
renderer->RenderModel(model, param);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
head = Matrix4::Translate(0.f, 0.f, -0.0f);
|
2013-09-21 04:17:34 +09:00
|
|
|
head = torso * head;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
arms = Matrix4::Translate(0.f, 0.f, 0.1f);
|
2013-09-21 04:17:34 +09:00
|
|
|
arms = torso * arms;
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
float armPitch = pitch;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (inp.sprint) {
|
2013-09-21 04:17:34 +09:00
|
|
|
armPitch -= .5f;
|
|
|
|
}
|
|
|
|
armPitch += pitchBias;
|
2016-12-03 18:23:47 +09:00
|
|
|
if (armPitch < 0.f) {
|
2013-09-21 04:17:34 +09:00
|
|
|
armPitch = std::max(armPitch, -(float)M_PI * .5f);
|
|
|
|
armPitch *= .9f;
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
arms = arms * Matrix4::Rotate(MakeVector3(1, 0, 0), armPitch);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-03 17:13:49 +01:00
|
|
|
model = renderer->RegisterModel("Models/Player/Arms.kv6");
|
2013-09-21 04:17:34 +09:00
|
|
|
param.matrix = arms * scaler;
|
|
|
|
renderer->RenderModel(model, param);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
head = head * Matrix4::Rotate(MakeVector3(1, 0, 0), pitch);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-03 17:13:49 +01:00
|
|
|
model = renderer->RegisterModel("Models/Player/Head.kv6");
|
2013-09-21 04:17:34 +09:00
|
|
|
param.matrix = head * scaler;
|
|
|
|
renderer->RenderModel(model, param);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// draw tool
|
|
|
|
{
|
|
|
|
ScriptIThirdPersonToolSkin interface(skin);
|
|
|
|
interface.SetOriginMatrix(arms);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
ScriptIToolSkin interface(skin);
|
|
|
|
interface.AddToScene();
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2017-02-25 21:19:19 +09:00
|
|
|
hasValidOriginMatrix = true;
|
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// draw intel in ctf
|
2019-07-17 00:31:00 +09:00
|
|
|
stmp::optional<IGameMode &> mode = world->GetMode();
|
2016-12-03 18:23:47 +09:00
|
|
|
if (mode && IGameMode::m_CTF == mode->ModeType()) {
|
2019-07-17 00:31:00 +09:00
|
|
|
CTFGameMode &ctfMode = dynamic_cast<CTFGameMode &>(*mode);
|
|
|
|
int tId = p.GetTeamId();
|
2016-12-03 18:23:47 +09:00
|
|
|
if (tId < 3) {
|
2019-07-17 00:31:00 +09:00
|
|
|
CTFGameMode::Team &team = ctfMode.GetTeam(p.GetTeamId());
|
|
|
|
if (team.hasIntel && team.carrier == p.GetId()) {
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
IntVector3 col2 = world->GetTeam(1 - p.GetTeamId()).color;
|
2016-12-03 18:23:47 +09:00
|
|
|
param.customColor =
|
|
|
|
MakeVector3(col2.x / 255.f, col2.y / 255.f, col2.z / 255.f);
|
|
|
|
Matrix4 mIntel = torso * Matrix4::Translate(0, 0.6f, 0.5f);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-03 17:13:49 +01:00
|
|
|
model = renderer->RegisterModel("Models/MapObjects/Intel.kv6");
|
2013-09-21 04:17:34 +09:00
|
|
|
param.matrix = mIntel * scaler;
|
|
|
|
renderer->RenderModel(model, param);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
param.customColor =
|
|
|
|
MakeVector3(col.x / 255.f, col.y / 255.f, col.z / 255.f);
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// third person player rendering, done
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
void ClientPlayer::AddToScene() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
Player &p = player;
|
|
|
|
const SceneDefinition &lastSceneDef = client.GetLastSceneDef();
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2017-02-25 21:19:19 +09:00
|
|
|
hasValidOriginMatrix = false;
|
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
if (p.GetTeamId() >= 2) {
|
2013-09-21 04:17:34 +09:00
|
|
|
// spectator, or dummy player
|
|
|
|
return;
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
float distancePowered = (p.GetOrigin() - lastSceneDef.viewOrigin).GetPoweredLength();
|
2016-12-03 18:23:47 +09:00
|
|
|
if (distancePowered > 140.f * 140.f) {
|
2013-09-21 04:17:34 +09:00
|
|
|
return;
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (!ShouldRenderInThirdPersonView()) {
|
2013-09-21 04:17:34 +09:00
|
|
|
AddToSceneFirstPersonView();
|
|
|
|
} else {
|
|
|
|
AddToSceneThirdPersonView();
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-01 00:39:17 +09:00
|
|
|
void ClientPlayer::Draw2D() {
|
2019-07-17 00:31:00 +09:00
|
|
|
if (!ShouldRenderInThirdPersonView() && player.IsAlive()) {
|
2013-11-01 00:39:17 +09:00
|
|
|
asIScriptObject *skin;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (currentTool == Player::ToolSpade) {
|
2013-11-01 00:39:17 +09:00
|
|
|
skin = spadeViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolBlock) {
|
2013-11-01 00:39:17 +09:00
|
|
|
skin = blockViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolGrenade) {
|
2013-11-01 00:39:17 +09:00
|
|
|
skin = grenadeViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else if (currentTool == Player::ToolWeapon) {
|
2013-11-01 00:39:17 +09:00
|
|
|
skin = weaponViewSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-11-01 00:39:17 +09:00
|
|
|
SPInvalidEnum("currentTool", currentTool);
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-01 00:39:17 +09:00
|
|
|
SetSkinParameterForTool(currentTool, skin);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-01 00:39:17 +09:00
|
|
|
SetCommonSkinParameter(skin);
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-11-01 00:39:17 +09:00
|
|
|
// common process
|
|
|
|
{
|
|
|
|
ScriptIViewToolSkin interface(skin);
|
|
|
|
interface.SetEyeMatrix(GetEyeMatrix());
|
|
|
|
interface.SetSwing(viewWeaponOffset);
|
|
|
|
interface.Draw2D();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
bool ClientPlayer::ShouldRenderInThirdPersonView() {
|
2017-12-05 15:42:24 +09:00
|
|
|
// The player from whom's perspective the game is
|
2019-07-17 00:31:00 +09:00
|
|
|
return !IsFirstPerson(client.GetCameraMode()) ||
|
|
|
|
&player != &client.GetCameraTargetPlayer();
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2017-01-06 04:01:10 +09:00
|
|
|
struct ClientPlayer::AmbienceInfo {
|
|
|
|
float room;
|
|
|
|
float size;
|
|
|
|
float distance;
|
|
|
|
};
|
|
|
|
|
|
|
|
ClientPlayer::AmbienceInfo ClientPlayer::ComputeAmbience() {
|
2019-07-17 00:31:00 +09:00
|
|
|
const SceneDefinition &lastSceneDef = client.GetLastSceneDef();
|
2017-01-07 01:38:56 +09:00
|
|
|
|
|
|
|
if (!cg_environmentalAudio) {
|
|
|
|
AmbienceInfo result;
|
|
|
|
result.room = 0.0f;
|
2019-07-17 00:31:00 +09:00
|
|
|
result.distance = (lastSceneDef.viewOrigin - player.GetEye()).GetLength();
|
2017-01-07 01:38:56 +09:00
|
|
|
result.size = 0.0f;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-01-06 04:01:10 +09:00
|
|
|
float maxDistance = 40.f;
|
2019-07-17 00:31:00 +09:00
|
|
|
GameMap *map = client.map;
|
2017-01-06 04:01:10 +09:00
|
|
|
SPAssert(map);
|
|
|
|
|
2019-07-17 00:31:00 +09:00
|
|
|
Vector3 rayFrom = player.GetEye();
|
2017-01-07 01:36:24 +09:00
|
|
|
// uniformly distributed random unit vectors
|
|
|
|
const Vector3 directions[24] = {
|
|
|
|
{-0.4806003057749437f, -0.42909622618705534f, 0.7647874049440525f},
|
|
|
|
{-0.32231294555647927f, 0.6282069816346844f, 0.7081457147735524f},
|
|
|
|
{0.048740582496498826f, -0.6670915238644523f, 0.7433796166200044f},
|
|
|
|
{0.4507022412112344f, 0.2196054264547812f, 0.8652403980621708f},
|
|
|
|
{-0.42721511627413183f, -0.587164590982542f, -0.6875499891085622f},
|
|
|
|
{-0.5570464880797501f, 0.3832470400156089f, -0.7367638131974799f},
|
|
|
|
{0.4379032819319448f, -0.5217172826725083f, -0.732155579528044f},
|
|
|
|
{0.5505793235065188f, 0.5884516130938041f, -0.5921039668625805f},
|
|
|
|
{0.681714179159347f, -0.6289005125058891f, -0.3738314102679548f},
|
|
|
|
{0.882424317058847f, 0.4680895178240496f, -0.047111866514457174f},
|
|
|
|
{0.8175844570742612f, -0.5123280060684333f, 0.26282250616819125f},
|
|
|
|
{0.7326555076593512f, 0.16938649523355995f, 0.6591844372623717f},
|
|
|
|
{-0.8833847855718798f, -0.46859333747646814f, -0.007183640636104698f},
|
|
|
|
{-0.6478926243769724f, 0.5325399055055595f, -0.5446433661783178f},
|
|
|
|
{-0.7011236289377749f, -0.4179353735633245f, 0.5777159167528706f},
|
|
|
|
{-0.8834742898471629f, 0.3226030059694268f, 0.3397064611080296f},
|
|
|
|
{-0.701272268659947f, 0.7126868112640804f, -0.017167243773185584f},
|
|
|
|
{-0.4048459451282839f, 0.8049148135357349f, 0.4338339586338529f},
|
|
|
|
{0.10511344475950758f, 0.7400485819463978f, -0.664288536774432f},
|
|
|
|
{0.4228172536676786f, 0.7759558485735245f, 0.46810051384874957f},
|
|
|
|
{-0.641642302739998f, -0.7293326298605313f, -0.23742171416118207f},
|
|
|
|
{-0.269582155924164f, -0.957885171758109f, 0.09890125850168793f},
|
|
|
|
{0.09274966874325204f, -0.9126579244190587f, -0.39806156803076687f},
|
|
|
|
{0.49359438685568013f, -0.721891173178783f, 0.48501310843226225f}};
|
|
|
|
std::array<float, 24> distances;
|
|
|
|
std::array<float, 24> feedbacknesses;
|
2017-01-06 04:01:10 +09:00
|
|
|
|
|
|
|
std::fill(feedbacknesses.begin(), feedbacknesses.end(), 0.0f);
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < distances.size(); ++i) {
|
|
|
|
float &distance = distances[i];
|
|
|
|
float &feedbackness = feedbacknesses[i];
|
|
|
|
|
2017-01-07 01:36:24 +09:00
|
|
|
const Vector3 &rayTo = directions[i];
|
2017-01-06 04:01:10 +09:00
|
|
|
|
|
|
|
IntVector3 hitPos;
|
|
|
|
bool hit = map->CastRay(rayFrom, rayTo, maxDistance, hitPos);
|
|
|
|
if (hit) {
|
|
|
|
Vector3 hitPosf = {(float)hitPos.x, (float)hitPos.y, (float)hitPos.z};
|
|
|
|
distance = (hitPosf - rayFrom).GetLength();
|
|
|
|
} else {
|
|
|
|
distance = maxDistance * 2.f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hit) {
|
|
|
|
bool hit2 = map->CastRay(rayFrom, -rayTo, maxDistance, hitPos);
|
|
|
|
if (hit2)
|
|
|
|
feedbackness = 1.f;
|
|
|
|
else
|
|
|
|
feedbackness = 0.f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// monte-carlo integration
|
|
|
|
unsigned int rayHitCount = 0;
|
|
|
|
float roomSize = 0.f;
|
|
|
|
float feedbackness = 0.f;
|
|
|
|
|
|
|
|
for (float dist : distances) {
|
|
|
|
if (dist < maxDistance) {
|
|
|
|
rayHitCount++;
|
|
|
|
roomSize += dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (float fb : feedbacknesses) {
|
|
|
|
feedbackness += fb;
|
|
|
|
}
|
|
|
|
|
|
|
|
float reflections;
|
|
|
|
if (rayHitCount > distances.size() / 4) {
|
|
|
|
roomSize /= (float)rayHitCount;
|
|
|
|
reflections = (float)rayHitCount / (float)distances.size();
|
|
|
|
} else {
|
|
|
|
reflections = 0.1f;
|
|
|
|
roomSize = 100.f;
|
|
|
|
}
|
|
|
|
|
|
|
|
feedbackness /= (float)distances.size();
|
2017-01-07 01:36:24 +09:00
|
|
|
feedbackness = std::min(std::max(0.0f, feedbackness - 0.35f) / 0.5f, 1.0f);
|
2017-01-06 04:01:10 +09:00
|
|
|
|
|
|
|
AmbienceInfo result;
|
|
|
|
result.room = reflections * feedbackness;
|
2019-07-17 00:31:00 +09:00
|
|
|
result.distance = (lastSceneDef.viewOrigin - player.GetEye()).GetLength();
|
2017-01-06 04:01:10 +09:00
|
|
|
result.size = std::max(std::min(roomSize / 15.0f, 1.0f), 0.0f);
|
|
|
|
result.room *= std::max(0.0f, std::min((result.size - 0.1f) * 4.0f, 1.0f));
|
|
|
|
result.room *= 1.0f - result.size * 0.3f;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
void ClientPlayer::FiredWeapon() {
|
2019-07-17 00:31:00 +09:00
|
|
|
World &world = player.GetWorld();
|
2013-09-21 04:17:34 +09:00
|
|
|
Vector3 muzzle;
|
2019-07-17 00:31:00 +09:00
|
|
|
const SceneDefinition &lastSceneDef = client.GetLastSceneDef();
|
|
|
|
IRenderer *renderer = client.GetRenderer();
|
|
|
|
IAudioDevice *audioDevice = client.GetAudioDevice();
|
|
|
|
Player &p = player;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
// make dlight
|
|
|
|
{
|
|
|
|
Vector3 vec;
|
|
|
|
Matrix4 eyeMatrix = GetEyeMatrix();
|
|
|
|
Matrix4 mat;
|
2016-12-03 18:23:47 +09:00
|
|
|
mat = Matrix4::Translate(-0.13f, .5f, 0.2f);
|
2013-09-21 04:17:34 +09:00
|
|
|
mat = eyeMatrix * mat;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
vec = (mat * MakeVector3(0, 1, 0)).GetXYZ();
|
|
|
|
muzzle = vec;
|
2019-07-17 00:31:00 +09:00
|
|
|
client.MuzzleFire(vec, player.GetFront(), &player == world.GetLocalPlayer());
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (cg_ejectBrass) {
|
2019-07-17 00:31:00 +09:00
|
|
|
float dist = (player.GetOrigin() - lastSceneDef.viewOrigin).GetPoweredLength();
|
2016-12-03 18:23:47 +09:00
|
|
|
if (dist < 130.f * 130.f) {
|
2013-09-21 04:17:34 +09:00
|
|
|
IModel *model = NULL;
|
|
|
|
Handle<IAudioChunk> snd = NULL;
|
|
|
|
Handle<IAudioChunk> snd2 = NULL;
|
2019-07-17 00:31:00 +09:00
|
|
|
switch (player.GetWeapon().GetWeaponType()) {
|
2013-09-21 04:17:34 +09:00
|
|
|
case RIFLE_WEAPON:
|
|
|
|
model = renderer->RegisterModel("Models/Weapons/Rifle/Casing.kv6");
|
2016-12-03 18:23:47 +09:00
|
|
|
snd =
|
2018-09-17 23:37:11 +09:00
|
|
|
SampleRandomBool()
|
2016-12-18 00:45:17 +09:00
|
|
|
? audioDevice->RegisterSound("Sounds/Weapons/Rifle/ShellDrop1.opus")
|
2017-01-06 04:01:10 +09:00
|
|
|
: audioDevice->RegisterSound(
|
|
|
|
"Sounds/Weapons/Rifle/ShellDrop2.opus");
|
2013-09-21 04:17:34 +09:00
|
|
|
snd2 =
|
2016-12-18 00:45:17 +09:00
|
|
|
audioDevice->RegisterSound("Sounds/Weapons/Rifle/ShellWater.opus");
|
2013-09-21 04:17:34 +09:00
|
|
|
break;
|
|
|
|
case SHOTGUN_WEAPON:
|
|
|
|
// FIXME: don't want to show shotgun't casing
|
|
|
|
// because it isn't ejected when firing
|
2016-12-03 18:23:47 +09:00
|
|
|
// model = renderer->RegisterModel("Models/Weapons/Shotgun/Casing.kv6");
|
2013-09-21 04:17:34 +09:00
|
|
|
break;
|
|
|
|
case SMG_WEAPON:
|
|
|
|
model = renderer->RegisterModel("Models/Weapons/SMG/Casing.kv6");
|
2016-12-03 18:23:47 +09:00
|
|
|
snd =
|
2018-09-17 23:37:11 +09:00
|
|
|
SampleRandomBool()
|
2016-12-18 00:45:17 +09:00
|
|
|
? audioDevice->RegisterSound("Sounds/Weapons/SMG/ShellDrop1.opus")
|
|
|
|
: audioDevice->RegisterSound("Sounds/Weapons/SMG/ShellDrop2.opus");
|
|
|
|
snd2 = audioDevice->RegisterSound("Sounds/Weapons/SMG/ShellWater.opus");
|
2013-09-21 04:17:34 +09:00
|
|
|
break;
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
if (model) {
|
2013-09-21 04:17:34 +09:00
|
|
|
Vector3 origin;
|
2019-07-17 00:31:00 +09:00
|
|
|
origin = muzzle - p.GetFront() * 0.5f;
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
Vector3 vel;
|
2019-07-17 00:31:00 +09:00
|
|
|
vel = p.GetFront() * 0.5f + p.GetRight() + p.GetUp() * 0.2f;
|
|
|
|
switch (p.GetWeapon().GetWeaponType()) {
|
|
|
|
case SMG_WEAPON: vel -= p.GetFront() * 0.7f; break;
|
2016-12-03 18:23:47 +09:00
|
|
|
case SHOTGUN_WEAPON: vel *= .5f; break;
|
|
|
|
default: break;
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
ILocalEntity *ent;
|
2019-07-17 00:31:00 +09:00
|
|
|
ent = new GunCasing(&client, model, snd, snd2, origin, p.GetFront(), vel);
|
|
|
|
client.AddLocalEntity(ent);
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2017-01-06 04:01:10 +09:00
|
|
|
// sound ambience estimation
|
|
|
|
auto ambience = ComputeAmbience();
|
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
asIScriptObject *skin;
|
2013-09-23 02:05:38 +09:00
|
|
|
// FIXME: what if current tool isn't weapon?
|
2016-12-03 18:23:47 +09:00
|
|
|
if (ShouldRenderInThirdPersonView()) {
|
2013-09-23 02:05:38 +09:00
|
|
|
skin = weaponSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-23 02:05:38 +09:00
|
|
|
skin = weaponViewSkin;
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2017-01-06 04:01:10 +09:00
|
|
|
{
|
|
|
|
ScriptIWeaponSkin2 interface(skin);
|
|
|
|
if (interface.ImplementsInterface()) {
|
2017-01-07 03:55:39 +09:00
|
|
|
interface.SetSoundEnvironment(ambience.room, ambience.size, ambience.distance);
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetSoundOrigin(player.GetEye());
|
2017-02-25 21:19:19 +09:00
|
|
|
} else if (ShouldRenderInThirdPersonView() && !hasValidOriginMatrix) {
|
|
|
|
// Legacy skin scripts rely on OriginMatrix which is only updated when
|
|
|
|
// the player's location is within the fog range.
|
|
|
|
return;
|
2017-01-06 04:01:10 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
{
|
|
|
|
ScriptIWeaponSkin interface(skin);
|
|
|
|
interface.WeaponFired();
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
void ClientPlayer::ReloadingWeapon() {
|
|
|
|
asIScriptObject *skin;
|
2013-09-23 02:05:38 +09:00
|
|
|
// FIXME: what if current tool isn't weapon?
|
2016-12-03 18:23:47 +09:00
|
|
|
if (ShouldRenderInThirdPersonView()) {
|
2013-09-23 02:05:38 +09:00
|
|
|
skin = weaponSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-23 02:05:38 +09:00
|
|
|
skin = weaponViewSkin;
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2017-02-25 21:19:19 +09:00
|
|
|
// sound ambience estimation
|
|
|
|
auto ambience = ComputeAmbience();
|
|
|
|
|
|
|
|
{
|
|
|
|
ScriptIWeaponSkin2 interface(skin);
|
|
|
|
if (interface.ImplementsInterface()) {
|
|
|
|
interface.SetSoundEnvironment(ambience.room, ambience.size, ambience.distance);
|
2019-07-17 00:31:00 +09:00
|
|
|
interface.SetSoundOrigin(player.GetEye());
|
2017-02-25 21:19:19 +09:00
|
|
|
} else if (ShouldRenderInThirdPersonView() && !hasValidOriginMatrix) {
|
|
|
|
// Legacy skin scripts rely on OriginMatrix which is only updated when
|
|
|
|
// the player's location is within the fog range.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
{
|
|
|
|
ScriptIWeaponSkin interface(skin);
|
|
|
|
interface.ReloadingWeapon();
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:13:00 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
void ClientPlayer::ReloadedWeapon() {
|
|
|
|
asIScriptObject *skin;
|
2013-09-23 02:05:38 +09:00
|
|
|
// FIXME: what if current tool isn't weapon?
|
2016-12-03 18:23:47 +09:00
|
|
|
if (ShouldRenderInThirdPersonView()) {
|
2013-09-23 02:05:38 +09:00
|
|
|
skin = weaponSkin;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-23 02:05:38 +09:00
|
|
|
skin = weaponViewSkin;
|
2013-09-21 04:17:34 +09:00
|
|
|
}
|
2013-09-23 02:05:38 +09:00
|
|
|
|
2013-09-21 04:17:34 +09:00
|
|
|
{
|
|
|
|
ScriptIWeaponSkin interface(skin);
|
|
|
|
interface.ReloadedWeapon();
|
|
|
|
}
|
|
|
|
}
|
2019-07-17 00:31:00 +09:00
|
|
|
} // namespace client
|
|
|
|
} // namespace spades
|