Added graphical obituaries for HL/SH.

The way the weapon is chosen is not yet final. I'm just tired and don't
feel like engineering the damage stuff right now.
This commit is contained in:
Marco Cawthorne 2019-09-04 18:11:55 +02:00
parent 53a12821e1
commit 5aa167d4af
44 changed files with 1270 additions and 689 deletions

View file

@ -61,6 +61,7 @@ defs.h
../../shared/decals.c
../../shared/effects.c
../../shared/spraylogo.cpp
../npc.c
overview.c
../player.c
@ -74,6 +75,7 @@ nightvision.c
hudcrosshair.c
hudscope.c
hudweaponselect.c
../obituary.c
hudorbituaries.c
hud.c
../vgui.cpp

View file

@ -80,5 +80,7 @@ CSQC_Parse_Damage(float save, float take, vector abs_pos)
pSeat->damage_alpha = 1.0f;
}
View_AddPunchAngle([take,0,0]);
return TRUE;
}

View file

@ -30,6 +30,9 @@ void CSQC_Ent_Update(float new)
case ENT_PLAYER:
Player_ReadEntity(new);
break;
case ENT_NPC:
NPC_ReadEntity(new);
break;
case ENT_SPRITE:
Sprite_Animated();
break;

View file

@ -286,6 +286,7 @@ CSQC_UpdateView(float w, float h, float focus)
HUD_Draw();
}
Obituary_Draw();
///HUD_DrawOrbituaries();
Voice_DrawHUD();
Chat_Draw();
@ -436,6 +437,9 @@ CSQC_Parse_Event(void)
float fHeader = readbyte();
switch (fHeader) {
case EV_OBITUARY:
Obituary_Parse();
break;
case EV_SPEAK:
string msg;
float pit;

85
src/client/npc.c Normal file
View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class monster_npc
{
int body;
int inited;
float frame_last;
virtual float() predraw;
};
float
monster_npc::predraw(void)
{
/* Only do this once whenever the ent pops into view */
if (!inited) {
setcustomskin(this, "", sprintf("geomset 1 %i\n", body));
inited = TRUE;
}
if (lerpfrac > 0) {
lerpfrac -= frametime * 5;
if (lerpfrac < 0) {
lerpfrac = 0;
}
}
if (frame != frame_last) {
frame2time = frame1time;
frame2 = frame_last;
frame_last = frame;
lerpfrac = 1.0f;
frame1time = 0.0f;
}
frame2time += clframetime;
frame1time += clframetime;
bonecontrol5 = getchannellevel(this, CHAN_VOICE) * 20;
addentity(this);
return PREDRAW_NEXT;
}
void
NPC_ReadEntity(float new)
{
monster_npc pl = (monster_npc)self;
if (new == TRUE) {
spawnfunc_monster_npc();
pl.classname = "npc";
pl.solid = SOLID_SLIDEBOX;
pl.drawmask = MASK_ENGINE;
pl.customphysics = Empty;
setsize( pl, VEC_HULL_MIN, VEC_HULL_MAX );
}
/* TODO: make these conditional */
pl.modelindex = readshort();
pl.origin[0] = readcoord();
pl.origin[1] = readcoord();
pl.origin[2] = readcoord();
pl.angles[1] = readfloat();
pl.angles[2] = readfloat();
pl.velocity[0] = readcoord();
pl.velocity[1] = readcoord();
pl.velocity[2] = readcoord();
pl.frame = readbyte();
pl.skin = readbyte();
pl.body = readbyte();
}

170
src/client/obituary.c Normal file
View file

@ -0,0 +1,170 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
extern vector g_hud_color;
#define OBITUARY_LINES 4
#define OBITUARY_TIME 5
typedef struct {
string strAttacker;
string strVictim;
/* icon */
string strImage;
vector vecPos;
vector vecSize;
vector vecXY;
vector vecWH;
} obituary_t;
obituary_t g_obituary[OBITUARY_LINES];
static int g_obituary_count;
float g_obituary_time;
void
Obituary_KillIcon(int id, float w)
{
#ifdef VALVE
vector spr_size;
if (w > 0) {
spr_size = drawgetimagesize(g_weapons[w].ki_spr);
print(sprintf("Weapon death: %d\n", w));
/* fill in the entries and calculate some in advance */
g_obituary[id].strImage = g_weapons[w].ki_spr;
g_obituary[id].vecPos = g_weapons[w].ki_xy;
g_obituary[id].vecSize = g_weapons[w].ki_size;
g_obituary[id].vecXY[0] = g_weapons[w].ki_xy[0] / spr_size[0];
g_obituary[id].vecXY[1] = g_weapons[w].ki_xy[1] / spr_size[1];
g_obituary[id].vecWH[0] = g_weapons[w].ki_size[0] / spr_size[0];
g_obituary[id].vecWH[1] = g_weapons[w].ki_size[1] / spr_size[1];
} else {
/* fill in the entries and calculate some in advance */
g_obituary[id].strImage = "sprites/640hud1.spr_0.tga";
g_obituary[id].vecPos = [192,224];
g_obituary[id].vecSize = [32,16];
g_obituary[id].vecXY[0] = 192 / 256;
g_obituary[id].vecXY[1] = 224 / 256;
g_obituary[id].vecWH[0] = 32 / 256;
g_obituary[id].vecWH[1] = 16 / 256;
}
#endif
}
void
Obituary_Add(string attacker, string victim, float weapon, float flags)
{
int i;
int x, y;
x = OBITUARY_LINES;
/* we're not full yet, so fill up the buffer */
if (g_obituary_count < x) {
y = g_obituary_count;
g_obituary[y].strAttacker = attacker;
g_obituary[y].strVictim = victim;
Obituary_KillIcon(y, weapon);
g_obituary_count++;
} else {
for (i = 0; i < (x-1); i++) {
g_obituary[i].strAttacker = g_obituary[i+1].strAttacker;
g_obituary[i].strVictim = g_obituary[i+1].strVictim;
g_obituary[i].strImage = g_obituary[i+1].strImage;
g_obituary[i].vecPos = g_obituary[i+1].vecPos;
g_obituary[i].vecSize = g_obituary[i+1].vecSize;
g_obituary[i].vecXY = g_obituary[i+1].vecXY;
g_obituary[i].vecWH = g_obituary[i+1].vecWH;
}
/* after rearranging, add the newest to the bottom. */
g_obituary[x-1].strAttacker = attacker;
g_obituary[x-1].strVictim = victim;
Obituary_KillIcon(x-1, weapon);
}
g_obituary_time = OBITUARY_TIME;
}
void Obituary_Draw(void)
{
int i;
vector vecPos;
drawfont = FONT_CON;
vecPos = video_mins + [video_res[0] - 18, 56];
if (g_obituary_time <= 0 && g_obituary_count > 0) {
for (i = 0; i < (OBITUARY_LINES-1); i++) {
g_obituary[i].strAttacker = g_obituary[i+1].strAttacker;
g_obituary[i].strVictim = g_obituary[i+1].strVictim;
g_obituary[i].strImage = g_obituary[i+1].strImage;
g_obituary[i].vecPos = g_obituary[i+1].vecPos;
g_obituary[i].vecSize = g_obituary[i+1].vecSize;
g_obituary[i].vecXY = g_obituary[i+1].vecXY;
g_obituary[i].vecWH = g_obituary[i+1].vecWH;
}
g_obituary[OBITUARY_LINES-1].strAttacker = "";
g_obituary_time = OBITUARY_TIME;
g_obituary_count--;
}
g_obituary_time -= clframetime;
if (g_obituary_time <= 0) {
return;
}
vector vecItem = vecPos;
for (i = 0; i < OBITUARY_LINES; i++) {
string a, v;
if (!g_obituary[i].strAttacker) {
return;
}
vecItem[0] = vecPos[0];
v = g_obituary[i].strVictim;
drawstring_r(vecItem + [0,2], v, [12,12], [1,1,1], 1.0f, 0);
vecItem[0] -= stringwidth(v, TRUE, [12,12]) + 4;
vecItem[0] -= g_obituary[i].vecSize[0];
drawsubpic(vecItem, g_obituary[i].vecSize, g_obituary[i].strImage, g_obituary[i].vecXY, g_obituary[i].vecWH, g_hud_color, 1.0f, DRAWFLAG_ADDITIVE);
a = g_obituary[i].strAttacker;
drawstring_r(vecItem + [-4,2], a, [12,12], [1,1,1], 1.0f, 0);
vecItem[1] += 18;
}
}
void
Obituary_Parse(void)
{
string attacker;
string victim;
float weapon;
float flags;
attacker = readstring();
victim = readstring();
weapon = readbyte();
flags = readbyte();
Obituary_Add(attacker, victim, weapon, flags);
}

View file

@ -38,23 +38,24 @@ decore.cpp
../../shared/decals.c
../../shared/effects.c
../../shared/spraylogo.cpp
../npc.c
../../shared/valve/items.h
../../shared/valve/weapons.h
../../shared/valve/w_crowbar.c
../../shared/valve/w_glock.c
../../shared/valve/w_python.c
../../shared/valve/w_mp5.c
../../shared/valve/w_crossbow.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_rpg.c
../../shared/valve/w_gauss.c
../../shared/valve/w_crowbar.c
../../shared/valve/w_egon.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_gauss.c
../../shared/valve/w_glock.c
../../shared/valve/w_handgrenade.c
../../shared/valve/w_tripmine.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_mp5.c
../../shared/valve/w_python.c
../../shared/valve/w_rpg.c
../../shared/valve/w_satchel.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_snark.c
../../shared/valve/w_tripmine.c
../../shared/valve/weapons.c
../../shared/valve/weapon_common.c
@ -68,6 +69,7 @@ decore.cpp
../valve/view.c
../view.c
../damage.c
../obituary.c
../chat.c
../vgui.cpp

View file

@ -16,31 +16,6 @@
float(entity foo, float chanid) getchannellevel = #0;
/* This really shouldn't be here, but it'll be fine for the time being */
.int initedsci;
float Scientist_PreDraw(void)
{
/* Only do this once whenever the ent pops into view */
if (!self.initedsci) {
setcustomskin(self, "", sprintf("geomset 1 %d\n", self.colormod[0]));
self.initedsci = TRUE;
}
self.bonecontrol5 = getchannellevel(self, CHAN_VOICE) * 20;
/* HACK: We're abusing this networked field, so reset */
self.colormod = [0,0,0];
addentity(self);
return PREDRAW_NEXT;
}
float Scientist_Update(float new)
{
if (new) {
self.predraw = Scientist_PreDraw;
self.drawmask = MASK_ENGINE;
}
return TRUE;
}
/*
=================
@ -62,9 +37,6 @@ void Client_Init(float apilevel, string enginename, float engineversion)
precache_model("sprites/w_cannon.spr");
BEAM_TRIPMINE = particleeffectnum("beam_tripmine");
/* FIXME: Replace with manual networking once I've got time? */
deltalisten("models/scientist.mdl", Scientist_Update, 0);
}
void Client_InitDone(void)

View file

@ -18,7 +18,6 @@
../../vgui/include.src
../util.c
init.c
../../gs-entbase/client.src
@ -35,23 +34,25 @@ init.c
../../shared/decals.c
../../shared/effects.c
../../shared/spraylogo.cpp
../npc.c
init.c
../../shared/scihunt/items.h
../../shared/scihunt/weapons.h
../../shared/valve/w_crowbar.c
../../shared/valve/w_glock.c
../../shared/valve/w_python.c
../../shared/valve/w_mp5.c
../../shared/valve/w_crossbow.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_rpg.c
../../shared/valve/w_gauss.c
../../shared/valve/w_crowbar.c
../../shared/valve/w_egon.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_gauss.c
../../shared/valve/w_glock.c
../../shared/valve/w_handgrenade.c
../../shared/valve/w_tripmine.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_mp5.c
../../shared/valve/w_python.c
../../shared/valve/w_rpg.c
../../shared/valve/w_satchel.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_snark.c
../../shared/valve/w_tripmine.c
../../shared/scihunt/w_cannon.c
../../shared/scihunt/w_chainsaw.c
../../shared/scihunt/w_hammer.c
@ -68,6 +69,7 @@ init.c
../valve/view.c
../view.c
../damage.c
../obituary.c
../chat.c
../vgui.cpp

View file

@ -18,6 +18,6 @@
void
drawstring_r(vector p, string t, vector s, vector c, float a, float f)
{
p[0] -= stringwidth(t, FALSE, s);
p[0] -= stringwidth(t, TRUE, s);
drawstring(p, t, s, c, a, f);
}

View file

@ -37,31 +37,30 @@ void Player_ReadEntity(float flIsNew)
pl.drawmask = MASK_ENGINE;
pl.customphysics = Empty;
setsize( pl, VEC_HULL_MIN, VEC_HULL_MAX );
print(sprintf("Player %g is csqc ent %i\n", pl.entnum, pl));
}
else
{
if (pl.entnum == player_localentnum) //FIXME: splitscreen
{
pSeat = &seats[0]; //FIXME: splitscreen
for (int i = pl.sequence+1; i <= servercommandframe; i++)
{
if (!getinputstate(i))
} else {
int i;
//FIXME: splitscreen
if (pl.entnum == player_localentnum) {
//FIXME: splitscreen
pSeat = &seats[0];
for (i = pl.sequence+1; i <= servercommandframe; i++) {
if (!getinputstate(i)) {
break; //erk?... too old?
}
input_sequence = i;
QPhysics_Run(pl);
}
//any differences in things that are read below are now officially from prediction misses.
/* any differences in things that are read below are now
* officially from prediction misses. */
}
}
pl.sequence = servercommandframe;
pl.modelindex = readshort(); //make conditional
pl.sequence = servercommandframe;
pl.modelindex = readshort(); // TODO: make conditional
pl.origin[0] = readcoord();
pl.origin[1] = readcoord();
pl.origin[2] = readcoord(); //make conditional
pl.origin[2] = readcoord(); // TODO: make conditional
pl.pitch = readfloat();
pl.angles[1] = readfloat();
pl.angles[2] = readfloat();
@ -69,23 +68,23 @@ void Player_ReadEntity(float flIsNew)
pl.velocity[1] = readcoord();
pl.velocity[2] = readcoord();
pl.flags = readfloat(); //make mostly conditional
pl.activeweapon = readbyte(); //make conditional
pl.activeweapon = readbyte(); // TODO: make conditional
warnifdiff("weapontime", pl.weapontime, readfloat()); //remove
pl.g_items = readfloat(); //make conditional
pl.health = readbyte(); //make conditional
pl.armor = readbyte(); //make conditional
pl.movetype = readbyte(); //make conditional
pl.view_ofs[2] = readfloat(); //make conditional
pl.viewzoom = readfloat(); //remove? or make conditional
pl.g_items = readfloat(); // TODO: make conditional
pl.health = readbyte(); // TODO: make conditional
pl.armor = readbyte(); // TODO: make conditional
pl.movetype = readbyte(); // TODO: make conditional
pl.view_ofs[2] = readfloat(); // TODO: make conditional
pl.viewzoom = readfloat(); //remove? or make conditional
warnifdiff("jumptime", pl.jumptime, readfloat()); //remove
warnifdiff("teletime", pl.teleport_time, readfloat()); //remove
pl.baseframe = readbyte(); //make conditional
pl.frame = readbyte(); //make conditional
pl.baseframe = readbyte(); // TODO: make conditional
pl.frame = readbyte(); // TODO: make conditional
pl.a_ammo1 = readbyte(); //make conditional
pl.a_ammo2 = readbyte(); //make conditional
pl.a_ammo3 = readbyte(); //make conditional
pl.a_ammo1 = readbyte(); // TODO: make conditional
pl.a_ammo2 = readbyte(); // TODO: make conditional
pl.a_ammo3 = readbyte(); // TODO: make conditional
warnifdiff("attack_next", pl.w_attack_next, readfloat()); //remove
warnifdiff("idle_next", pl.w_idle_next, readfloat()); //remove
setorigin( pl, pl.origin );

View file

@ -35,23 +35,24 @@ init.c
../../shared/decals.c
../../shared/effects.c
../../shared/spraylogo.cpp
../npc.c
../../shared/valve/items.h
../../shared/valve/weapons.h
../../shared/valve/w_crowbar.c
../../shared/valve/w_glock.c
../../shared/valve/w_python.c
../../shared/valve/w_mp5.c
../../shared/valve/w_crossbow.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_rpg.c
../../shared/valve/w_gauss.c
../../shared/valve/w_crowbar.c
../../shared/valve/w_egon.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_gauss.c
../../shared/valve/w_glock.c
../../shared/valve/w_handgrenade.c
../../shared/valve/w_tripmine.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_mp5.c
../../shared/valve/w_python.c
../../shared/valve/w_rpg.c
../../shared/valve/w_satchel.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_snark.c
../../shared/valve/w_tripmine.c
../../shared/valve/weapons.c
../../shared/valve/weapon_common.c
@ -65,6 +66,7 @@ game_event.c
view.c
../view.c
../damage.c
../obituary.c
../chat.c
../vgui.cpp

View file

@ -16,6 +16,7 @@
enum {
ENT_PLAYER = 1,
ENT_NPC,
ENT_AMBIENTSOUND,
ENT_SPRITE,
ENT_SPRAY,

View file

@ -119,6 +119,7 @@ void CBaseEntity :: Respawn ( void )
void CBaseEntity :: Hide ( void )
{
setmodel( this, "" );
modelindex = 0;
solid = SOLID_NOT;
movetype = MOVETYPE_NONE;
takedamage = DAMAGE_NO;

View file

@ -17,7 +17,7 @@
var int g_initialized = FALSE;
const string LICENSE_TEXT = "\
========================================================================\
==============================================================================\
Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>\
\
Permission to use, copy, modify, and distribute this software for any\
@ -31,7 +31,7 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\
WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER\
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING\
OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\
========================================================================";
==============================================================================";
void cvar_init(void)
{
@ -134,10 +134,12 @@ void m_draw(vector screensize)
oldtime = time;
}
/*void m_drawloading(vector screensize, float opaque)
void m_drawloading(vector screensize, float opaque)
{
}*/
vector pos;
pos = (screensize / 2) - [32,32];
drawpic(pos, "gfx/lambda64", [64,64], [1,1,1], 1.0f);
}
float Menu_InputEvent(float evtype, float scanx, float chary, float devid)
{

File diff suppressed because it is too large Load diff

58
src/menu-vgui/ui_quitgame.cpp Executable file
View file

@ -0,0 +1,58 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
int g_iQuitGameInitialized;
void UI_QuitGame_Show ( void )
{
static CUIWindow winQuitGame;
static CUILabel lblSure;
static CUIButton btnQuit;
static CUIButton btnCancel;
static void QuitGame_Yes ( void ) {
winQuitGame.Hide();
localcmd( "quit\n" );
}
static void QuitGame_No ( void ) {
winQuitGame.Hide();
}
if ( !g_iQuitGameInitialized ) {
g_iQuitGameInitialized = TRUE;
winQuitGame = spawn( CUIWindow );
winQuitGame.SetTitle( "Quit Game" );
winQuitGame.SetSize( '256 128' );
winQuitGame.SetIcon( "textures/ui/icons/cancel" );
g_uiDesktop.Add( winQuitGame );
btnQuit = spawn( CUIButton );
btnQuit.SetTitle( "Quit" );
btnQuit.SetSize( '64 24' );
btnQuit.SetPos( winQuitGame.GetSize() - '152 32' );
btnCancel = spawn( CUIButton );
btnCancel.SetTitle( "Cancel" );
btnCancel.SetSize( '64 24' );
btnCancel.SetPos( winQuitGame.GetSize() - '80 32' );
lblSure = spawn( CUILabel );
lblSure.SetTitle( "Do you wish to stop playing now?" );
lblSure.SetSize( '256 16' );
lblSure.SetPos( '0 48' );
btnQuit.SetFunc( QuitGame_Yes );
btnCancel.SetFunc( QuitGame_No );
winQuitGame.Add( btnQuit );
winQuitGame.Add( btnCancel );
winQuitGame.Add( lblSure );
}
winQuitGame.Show();
winQuitGame.SetPos( ( video_res / 2 ) - ( winQuitGame.GetSize() / 2 ) );
}

106
src/plugins/chatsounds.c Executable file
View file

@ -0,0 +1,106 @@
/*
Copyright 2019 <marco@icculus.org>
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_chatplug_suppresschat = 0;
entity csndemitter;
typedef struct {
string sentence;
string sample;
} chatsentence_t;
chatsentence_t *g_chatsounds;
var int g_chatsounds_count;
int ChatLookUp(string cmd)
{
for (int i = 0; i < g_chatsounds_count; i++) {
int sc = tokenizebyseparator(g_chatsounds[i].sentence, ";");
for (int c = 0; c < sc; c++) {
if (cmd == argv(c)) {
int count = tokenizebyseparator(g_chatsounds[i].sample, ";");
int r = random(0, count);
sound(csndemitter, CHAN_BODY, argv(r), 1.0f, ATTN_NONE, 100, SOUNDFLAG_NOREVERB);
break;
}
}
}
/* Some jokester might set it to non 0/1 */
return autocvar_chatplug_suppresschat == 1 ? TRUE : FALSE;
}
int FMX_ParseClientCommand(string cmd)
{
tokenize(cmd);
switch (argv(0)) {
case "say":
return ChatLookUp(strtolower(argv(1)));
break;
default:
return FALSE;
}
return TRUE;
}
void initents(void)
{
/* Why waste entity slots? */
if (g_chatsounds_count > 0) {
csndemitter = spawn();
}
}
void init(float prevprogs)
{
filestream chatfile;
chatfile = fopen("chatsounds.txt", FILE_READ);
if (chatfile >= 0) {
string temp;
int i = 0;
int c = 0;
/* count lines */
while ((temp = fgets(chatfile))) {
c = tokenize_console(temp);
if (c != 2) {
continue;
}
g_chatsounds_count++;
}
fseek(chatfile, 0);
print(sprintf("Chat Sound Plugin: %i record(s) initialized\n", g_chatsounds_count));
g_chatsounds = memalloc(sizeof(chatsentence_t) * g_chatsounds_count);
while ((temp = fgets(chatfile))) {
c = tokenize_console(temp);
if (c != 2 ) {
continue;
}
g_chatsounds[i].sentence = strtolower(argv(0));
g_chatsounds[i].sample = strtolower(argv(1));
c = tokenizebyseparator(g_chatsounds[i].sample, ";");
for (int x = 0; x < c; x++) {
precache_sound(argv(x));
print(sprintf("Caching: %s\n", argv(x)));
}
i++;
}
fclose(chatfile);
} else {
print("Chat Sound Plugin: chatsounds.txt not found.\n");
}
}

8
src/plugins/chatsounds.src Executable file
View file

@ -0,0 +1,8 @@
#pragma target fte
#pragma PROGS_DAT "../../valve/data.pk3dir/p_chatsounds.dat"
#define QWSSQC
#includelist
../builtins.h
chatsounds.c
#endlist

View file

@ -37,20 +37,20 @@ monster_human_unarmed.cpp
../valve/spectator.c
../../shared/valve/items.h
../../shared/valve/weapons.h
../../shared/valve/w_crowbar.c
../../shared/valve/w_glock.c
../../shared/valve/w_python.c
../../shared/valve/w_mp5.c
../../shared/valve/w_crossbow.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_rpg.c
../../shared/valve/w_gauss.c
../../shared/valve/w_crowbar.c
../../shared/valve/w_egon.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_gauss.c
../../shared/valve/w_glock.c
../../shared/valve/w_handgrenade.c
../../shared/valve/w_tripmine.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_mp5.c
../../shared/valve/w_python.c
../../shared/valve/w_rpg.c
../../shared/valve/w_satchel.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_snark.c
../../shared/valve/w_tripmine.c
../valve/items.cpp
../valve/item_longjump.cpp
../valve/item_suit.cpp

View file

@ -246,7 +246,13 @@ string sci_sndscream[] = {
"scientist/youinsane.wav",
"scientist/scream23.wav",
"scientist/scream24.wav",
"scientist/scream25.wav"
"scientist/scream25.wav",
"scientist/whatyoudoing.wav",
"scientist/canttakemore.wav",
"scientist/madness.wav",
"scientist/noplease.wav",
"scientist/getoutofhere.wav",
"scientist/sorryimleaving.wav",
};
string sci_sndstop[] = {
@ -279,13 +285,28 @@ string sci_snduseno[] = {
"scientist/whyleavehere.wav"
};
string sci_sndidle[] = {
"scientist/hideglasses.wav",
"scientist/weartie.wav",
"scientist/runtest.wav",
"scientist/limitsok.wav",
"scientist/asexpected.wav",
"scientist/thatsodd.wav",
"scientist/allnominal.wav",
"scientist/shutdownchart.wav",
"scientist/reportflux.wav",
"scientist/simulation.wav",
"scientist/hopenominal.wav",
};
class monster_scientist:CBaseEntity
{
int m_iBody;
vector m_vecLastUserPos;
entity m_eUser;
entity m_eRescuer;
float m_flScaredTime;
float m_flScreamTime;
float m_flPainTime;
float m_flChangePath;
@ -303,10 +324,34 @@ class monster_scientist:CBaseEntity
virtual void() Physics;
virtual void() Scream;
virtual void() Gib;
virtual float(entity, float) SendEntity;
virtual void() WarnOthers;
virtual void(string) Speak;
virtual void() IdleChat;
};
float monster_scientist::SendEntity(entity ePEnt, float fChanged)
{
if (modelindex == 0) {
return FALSE;
}
WriteByte(MSG_ENTITY, ENT_NPC);
WriteShort(MSG_ENTITY, modelindex);
WriteCoord(MSG_ENTITY, origin[0]);
WriteCoord(MSG_ENTITY, origin[1]);
WriteCoord(MSG_ENTITY, origin[2]);
WriteFloat(MSG_ENTITY, angles[1]);
WriteFloat(MSG_ENTITY, angles[2]);
WriteCoord(MSG_ENTITY, velocity[0]);
WriteCoord(MSG_ENTITY, velocity[1]);
WriteCoord(MSG_ENTITY, velocity[2]);
WriteByte(MSG_ENTITY, frame);
WriteByte(MSG_ENTITY, skin);
WriteByte(MSG_ENTITY, m_iBody);
return TRUE;
}
void monster_scientist::Speak(string msg)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
@ -330,9 +375,11 @@ void monster_scientist::WarnOthers(void)
for (entity b = world; (b = find(b, ::classname, "monster_scientist"));) {
if (vlen(b.origin - origin) < 512) {
monster_scientist sci = (monster_scientist)b;
sci.m_iFlags |= SCIF_FEAR | SCIF_SEEN;
sci.m_iFlags |= SCIF_SCARED | SCIF_FEAR | SCIF_SEEN;
sci.m_eUser = world;
sci.m_eRescuer = world;
sci.m_flScaredTime = time + 2.5f;
sci.Scream();
}
}
}
@ -348,6 +395,17 @@ void monster_scientist::Scream(void)
m_flScreamTime = time + 5.0f;
}
void monster_scientist::IdleChat(void)
{
if (m_flScreamTime > time) {
return;
}
int rand = floor(random(0,sci_sndchitchat.length));
Speak(sci_sndchitchat[rand]);
m_flScreamTime = time + 5.0f + random(0,20);
}
void monster_scientist::Physics(void)
{
float spvel;
@ -425,12 +483,13 @@ void monster_scientist::Physics(void)
}
}
} else if (m_iFlags & SCIF_FEAR) {
m_iFlags |= SCIF_SEEN;
Scream();
maxspeed = 240 * (autocvar_sh_scispeed/40);
input_movevalues = [maxspeed, 0, 0];
if (m_flTraceTime < time) {
traceline(self.origin, self.origin + (v_forward * 32), FALSE, this);
traceline(origin, origin + (v_forward * 64), FALSE, this);
if (trace_fraction < 1.0f) {
m_flChangePath = 0.0f;
@ -439,10 +498,33 @@ void monster_scientist::Physics(void)
}
if (m_flChangePath < time) {
v_angle[1] -= 180 + (random(-25, 25));
v_angle[1] = Math_FixDelta(v_angle[1]);
float add;
vector pos;
pos = origin + [0,0,-18];
if (random() < 0.5) {
add = 45;
} else {
add = -45;
}
/* test every 45 degrees */
for (int i = 0; i < 8; i++) {
v_angle[1] = Math_FixDelta(v_angle[1] + add);
makevectors(v_angle);
traceline(pos, pos + (v_forward * 64), FALSE, this);
if (trace_fraction >= 1.0f) {
break;
}
}
m_flChangePath = time + floor(random(2,10));
}
} else {
IdleChat();
}
if (m_flScaredTime < time && m_iFlags & SCIF_SCARED) {
m_iFlags &= ~SCIF_SCARED;
}
input_angles = angles = v_angle;
@ -464,6 +546,7 @@ void monster_scientist::Physics(void)
runstandardplayerphysics(this);
Footsteps_Update();
SendFlags = 1;
if (!(flags & FL_ONGROUND) && velocity[2] < -100) {
if (!(m_iFlags & SCIF_FALLING)) {
@ -541,6 +624,7 @@ void monster_scientist::vDeath(int iHitBody)
think = Respawn;
nextthink = time + 10.0f;
SendFlags = 1;
m_eUser = world;
customphysics = __NULL__;
m_iFlags = 0x0;
@ -550,6 +634,7 @@ void monster_scientist::vDeath(int iHitBody)
return;
}
flags &= ~FL_MONSTER;
movetype = MOVETYPE_NONE;
solid = SOLID_CORPSE;
//takedamage = DAMAGE_NO;
@ -575,6 +660,7 @@ void monster_scientist::Respawn(void)
v_angle[1] = Math_FixDelta(m_oldAngle[1]);
v_angle[2] = Math_FixDelta(m_oldAngle[2]);
flags |= FL_MONSTER;
setorigin(this, m_oldOrigin);
angles = v_angle;
solid = SOLID_SLIDEBOX;
@ -616,6 +702,9 @@ void monster_scientist::monster_scientist(void)
for (int i = 0; i < sci_sndsee.length; i++) {
precache_sound(sci_sndsee[i]);
}
for (int i = 0; i < sci_sndidle.length; i++) {
precache_sound(sci_sndidle[i]);
}
model = "models/scientist.mdl";
CBaseEntity::CBaseEntity();
@ -624,20 +713,24 @@ void monster_scientist::monster_scientist(void)
/* This stuff needs to be persistent because we can't guarantee that
* the client-side geomset refresh happens. Don't shove this into Respawn */
colormod[0] = floor(random(1,5));
switch (colormod[0]) {
m_iBody = floor(random(1,5));
switch (m_iBody) {
case 1:
m_flPitch = 105; // Walter
m_flPitch = 105;
netname = "Walter";
break;
case 2:
m_flPitch = 100; // Einstein
m_flPitch = 100;
netname = "Einstein";
break;
case 3:
m_flPitch = 95; // Luther
m_flPitch = 95;
netname = "Luther";
skin = 1;
break;
default:
m_flPitch = 100; // Slick
m_flPitch = 100;
netname = "Slick";
}
}

View file

@ -33,20 +33,20 @@ monster_scientist.cpp
../valve/spectator.c
../../shared/scihunt/items.h
../../shared/scihunt/weapons.h
../../shared/valve/w_crowbar.c
../../shared/valve/w_glock.c
../../shared/valve/w_python.c
../../shared/valve/w_mp5.c
../../shared/valve/w_crossbow.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_rpg.c
../../shared/valve/w_gauss.c
../../shared/valve/w_crowbar.c
../../shared/valve/w_egon.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_gauss.c
../../shared/valve/w_glock.c
../../shared/valve/w_handgrenade.c
../../shared/valve/w_tripmine.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_mp5.c
../../shared/valve/w_python.c
../../shared/valve/w_rpg.c
../../shared/valve/w_satchel.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_snark.c
../../shared/valve/w_tripmine.c
../../shared/scihunt/w_cannon.c
../../shared/scihunt/w_chainsaw.c
../../shared/scihunt/w_hammer.c

View file

@ -16,16 +16,16 @@
/* someone dieded */
void
Damage_CastObituary(entity eCulprit, entity eTarget, float weapon, float flags)
Damage_Obituary(entity eCulprit, entity eTarget, float weapon, float flags)
{
/*WriteByte(MSG_BROADCAST, SVC_CGAMEPACKET);
WriteByte(MSG_BROADCAST, EV_OBITUARY);
WriteByte(MSG_BROADCAST, num_for_edict(eCulprit) - 1);
WriteByte(MSG_BROADCAST, num_for_edict(eTarget) - 1);
WriteByte(MSG_BROADCAST, weapon);
WriteByte(MSG_BROADCAST, flags);
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_OBITUARY);
WriteString(MSG_MULTICAST, eCulprit.netname);
WriteString(MSG_MULTICAST, eTarget.netname);
WriteByte(MSG_MULTICAST, weapon);
WriteByte(MSG_MULTICAST, flags);
msg_entity = self;
multicast([0,0,0], MULTICAST_ALL);*/
multicast([0,0,0], MULTICAST_ALL);
}
/* generic function that applies damage, pain and suffering */
@ -73,19 +73,28 @@ Damage_Apply(entity eTarget, entity eCulprit, float fDmg, vector pos, int a)
forceinfokey(eTarget, "*deaths", ftos(eTarget.deaths));
}
if (eCulprit.flags & FL_CLIENT) {
if (eTarget == eCulprit) {
if (eTarget.flags & FL_CLIENT || eTarget.flags & FL_MONSTER)
if (eCulprit.flags & FL_CLIENT)
if (eTarget == eCulprit)
eCulprit.frags--;
} else {
else
eCulprit.frags++;
}
}
}
entity eOld = self;
self = eTarget;
if (self.health <= 0) {
if (eTarget.flags & FL_MONSTER || eTarget.flags & FL_CLIENT) {
float w = 0;
/* FIXME: this is unreliable. the culprit might have
* already switched weapons. FIX THIS */
if (eCulprit.flags & FL_CLIENT) {
player pl = (player)eCulprit;
w = pl.activeweapon;
}
Damage_Obituary(eCulprit, eTarget, w, 0);
}
self.vDeath(trace_surface_id);
} else {
self.vPain(trace_surface_id);

View file

@ -114,6 +114,7 @@ Player_SendEntity
float Player_SendEntity(entity ePEnt, float fChanged)
{
player pl = (player)self;
if (pl.health <= 0 && ePEnt != pl) {
return FALSE;
}

View file

@ -32,20 +32,20 @@ player.c
spectator.c
../../shared/valve/items.h
../../shared/valve/weapons.h
../../shared/valve/w_crowbar.c
../../shared/valve/w_glock.c
../../shared/valve/w_python.c
../../shared/valve/w_mp5.c
../../shared/valve/w_crossbow.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_rpg.c
../../shared/valve/w_gauss.c
../../shared/valve/w_crowbar.c
../../shared/valve/w_egon.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_gauss.c
../../shared/valve/w_glock.c
../../shared/valve/w_handgrenade.c
../../shared/valve/w_tripmine.c
../../shared/valve/w_hornetgun.c
../../shared/valve/w_mp5.c
../../shared/valve/w_python.c
../../shared/valve/w_rpg.c
../../shared/valve/w_satchel.c
../../shared/valve/w_shotgun.c
../../shared/valve/w_snark.c
../../shared/valve/w_tripmine.c
items.cpp
item_longjump.cpp
item_suit.cpp

View file

@ -223,6 +223,9 @@ weapon_t w_cannon =
ITEM_CANNON,
2,
3,
"sprites/640hud1.spr_0.tga",
[48,16],
[192,80],
w_cannon_draw,
w_cannon_holster,
w_cannon_primary,

View file

@ -152,6 +152,9 @@ weapon_t w_chainsaw =
ITEM_CHAINSAW,
0,
2,
"sprites/640hud1.spr_0.tga",
[48,16],
[192,80],
w_chainsaw_draw,
w_chainsaw_holster,
w_chainsaw_primary,

View file

@ -218,6 +218,9 @@ weapon_t w_hammer =
ITEM_HAMMER,
0,
1,
"sprites/640hud1.spr_0.tga",
[48,16],
[192,80],
w_hammer_draw,
w_hammer_holster,
w_hammer_primary,

View file

@ -20,6 +20,10 @@ typedef struct
int slot;
int slot_pos;
string ki_spr;
vector ki_size;
vector ki_xy;
void() draw;
void() holster;
void() primary;

View file

@ -259,6 +259,9 @@ weapon_t w_crossbow =
ITEM_CROSSBOW,
2,
2,
"sprites/640hud1.spr_0.tga",
[48,16],
[192,80],
w_crossbow_draw,
w_crossbow_holster,
w_crossbow_primary,

View file

@ -174,6 +174,9 @@ weapon_t w_crowbar =
ITEM_CROWBAR,
0,
0,
"sprites/640hud1.spr_0.tga",
[48,16],
[192,0],
w_crowbar_draw,
w_crowbar_holster,
w_crowbar_primary,

View file

@ -168,6 +168,9 @@ weapon_t w_egon =
ITEM_EGON,
3,
2,
"sprites/640hud1.spr_0.tga",
[32,16],
[192,128],
w_egon_draw,
w_egon_holster,
w_egon_primary,

View file

@ -382,6 +382,9 @@ weapon_t w_gauss =
ITEM_GAUSS,
3,
1,
"sprites/640hud1.spr_0.tga",
[32,16],
[192,112],
w_gauss_draw,
w_gauss_holster,
w_gauss_primary,

View file

@ -248,6 +248,9 @@ weapon_t w_glock =
ITEM_GLOCK,
1,
0,
"sprites/640hud1.spr_0.tga",
[32,16],
[192,16],
w_glock_draw,
w_glock_holster,
w_glock_primary,

View file

@ -232,6 +232,9 @@ weapon_t w_handgrenade =
ITEM_HANDGRENADE,
4,
0,
"sprites/640hud1.spr_0.tga",
[32,16],
[192,160],
w_handgrenade_draw,
w_handgrenade_holster,
w_handgrenade_primary,

View file

@ -240,6 +240,9 @@ weapon_t w_hornetgun =
ITEM_HORNETGUN,
3,
3,
"sprites/640hud1.spr_0.tga",
[48,16],
[192,144],
w_hornetgun_draw,
w_hornetgun_holster,
w_hornetgun_primary,

View file

@ -266,6 +266,9 @@ weapon_t w_mp5 = {
ITEM_MP5,
2,
0,
"sprites/640hud1.spr_0.tga",
[48,16],
[192,48],
w_mp5_draw,
w_mp5_holster,
w_mp5_primary,

View file

@ -214,6 +214,9 @@ weapon_t w_python =
ITEM_PYTHON,
1,
1,
"sprites/640hud1.spr_0.tga",
[32,16],
[192,32],
w_python_draw,
w_python_holster,
w_python_primary,

View file

@ -240,6 +240,9 @@ weapon_t w_rpg =
ITEM_RPG,
3,
0,
"sprites/640hud1.spr_0.tga",
[48,16],
[192,96],
w_rpg_draw,
w_rpg_holster,
w_rpg_primary,

View file

@ -251,6 +251,9 @@ weapon_t w_satchel =
ITEM_SATCHEL,
4,
1,
"sprites/640hud1.spr_0.tga",
[32,16],
[192,176],
w_satchel_draw,
w_satchel_holster,
w_satchel_primary,

View file

@ -283,6 +283,9 @@ weapon_t w_shotgun =
ITEM_SHOTGUN,
2,
1,
"sprites/640hud1.spr_0.tga",
[48,16],
[192,64],
w_shotgun_draw,
w_shotgun_holster,
w_shotgun_primary,

View file

@ -109,6 +109,7 @@ void w_snark_deploy(void)
static void snark_pain(int i) { }
entity snark = spawn();
snark.owner = self;
snark.netname = "Snark";
snark.classname = "snark";
setmodel(snark, "models/w_squeak.mdl");
makevectors(self.v_angle);
@ -259,6 +260,9 @@ weapon_t w_snark =
ITEM_SNARK,
4,
3,
"sprites/640hud1.spr_0.tga",
[32,16],
[192,208],
w_snark_draw,
w_snark_holster,
w_snark_primary,

View file

@ -273,6 +273,9 @@ weapon_t w_tripmine =
ITEM_TRIPMINE,
4,
2,
"sprites/640hud1.spr_0.tga",
[32,16],
[192,192],
w_tripmine_draw,
w_tripmine_holster,
w_tripmine_primary,

View file

@ -19,6 +19,9 @@ typedef struct
int id; /* bitflag id */
int slot;
int slot_pos;
string ki_spr;
vector ki_size;
vector ki_xy;
void() draw;
void() holster;