djcev.com

//

Git Repos / fte_dogmode / qc / monsters / demon.qc

Last update to this file was on 2024-04-12 at 18:56.

Show demon.qc

//==============================================================================
// DEMON
//==============================================================================

//======================================================================
// constants
//======================================================================

const float DEMON1_HEALTH = 300; // id1 300

const vector DEMON1_HEAD_MINS = '-13.64 -16.77 -0.11';
const vector DEMON1_HEAD_MAXS = '17.44 16.22 30';

//======================================================================
// forward declarations
//======================================================================

// monster_demon1
// float() monster_demon1_checkmelee; // AI & attacks
float() monster_demon1_checkjump;
float() monster_demon1_checkattack;
void() monster_demon1_sightsound;
void(float side) monster_demon1_melee; // thinking & animation below
void() dem1_stand1; void() dem1_stand2; void() dem1_stand3; void() dem1_stand4;
void() dem1_stand5; void() dem1_stand6; void() dem1_stand7; void() dem1_stand8;
void() dem1_stand9; void() dem1_stand10; void() dem1_stand11;
void() dem1_stand12; void() dem1_stand13;
void() dem1_walk1; void() dem1_walk2; void() dem1_walk3; void() dem1_walk4;
void() dem1_walk5; void() dem1_walk6; void() dem1_walk7; void() dem1_walk8;
void() dem1_run1; void() dem1_run2; void() dem1_run3; void() dem1_run4;
void() dem1_run5; void() dem1_run6;
void() dem1_jump1; void() dem1_jump2; void() dem1_jump3; void() dem1_jump4;
void() dem1_jump5; void() dem1_jump6; void() dem1_jump7; void() dem1_jump8;
void() dem1_jump9; void() dem1_jump10; void() dem1_jump11; void() dem1_jump12;
void() dem1_atk1; void() dem1_atk2; void() dem1_atk3; void() dem1_atk4;
void() dem1_atk5; void() dem1_atk6; void() dem1_atk7; void() dem1_atk8;
void() dem1_atk9; void() dem1_atk10; void() dem1_atk11; void() dem1_atk12;
void() dem1_atk13; void() dem1_atk14; void() dem1_atk15;
void() dem1_pain1; void() dem1_pain2; void() dem1_pain3; void() dem1_pain4;
void() dem1_pain5; void() dem1_pain6;
void() dem1_die1; void() dem1_die2; void() dem1_die3; void() dem1_die4;
void() dem1_die5; void() dem1_die6; void() dem1_die7; void() dem1_die8;
void() dem1_die9;
void(entity attacker, float damage) monster_demon1_pain; // interaction
void(vector dir) monster_demon1_destroy;
void() monster_demon1_touch;
void(entity e) monster_demon1_init; // initialization
void() monster_demon1;

// gib_head_demon
void(entity act, vector dir, float dmg) throw_gib_head_demon;
void(entity e) gib_head_demon_init;
void() gib_head_demon;

// monster_dead_demon
void() monster_dead_demon;

//======================================================================
// frame macros
//======================================================================

$cd id1/models/demon3
$scale 0.8
$origin 0 0 24
$base base
$skin base

$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9
$frame stand10 stand11 stand12 stand13

$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8

$frame run1 run2 run3 run4 run5 run6

$frame leap1 leap2 leap3 leap4 leap5 leap6 leap7 leap8 leap9 leap10
$frame leap11 leap12

$frame pain1 pain2 pain3 pain4 pain5 pain6

$frame death1 death2 death3 death4 death5 death6 death7 death8 death9

$frame attacka1 attacka2 attacka3 attacka4 attacka5 attacka6 attacka7 attacka8
$frame attacka9 attacka10 attacka11 attacka12 attacka13 attacka14 attacka15

//------------------------------------------------------------------------------

/*QUAKED monster_demon1 (1 0 0) (-32 -32 -24) (32 32 64) AMBUSH X X TRIGGER_SPAWNED X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ("progs/demon.mdl");
}
Fiend.

Default heath = 300"

snd_death(string) : "Path to custom death sound"
snd_pain(string) : ""Path to custom pain sound"
snd_sight(string) : "Path to custom sight sound"
snd_attack(string) : "Path to custom attack sound"
snd_hit(string) : "Path to custom hit sound (DEMON SLASHING)"
snd_idle(string) : "Path to custom idle sound"

mdl_head(string) : "Path to custom head model"
mdl_body(string) : "Path to custom body model"
skin_head(float) : "Skin index of custom head model"
mdl_gib1(string) : "Path to custom 1st gib model"

effects(choices) : "Add a visual effect to an entity"
0 : "None (Default)"
1 : "Brightfield (yellow particles)"
4 : "Bright light"
8 : "Dim light"

berserk(choices) "Skips certain pain animations similar to skill 3 (Makes a semi-nightmare monster!)"
0 : "Off (Default)"
1 : "Berserk (skip pain animations)"

delay(float) : "Delay spawn in for this amount of time"

wait(choices) : "Play an effect when trigger spawned?"
0 : "Teleport Effects (Default)"
1 : "Spawn Silently"

spawn_angry(Choices)
0 : "Only when trigger spawned, default behavior - not angry"
1 : "Only when trigger spawned, set to 1 to spawn angry at player"

infight_mode(Choices)
0 : "Default behavior, only with different classnames"
1 : "Infight with monsters with the same classname but a different mdl_body"
2 : "Infight with monsters with the same classname and model but a different skin"
3 : "Infight no matter what"

health(integer) : "Set this to a custom health amount"
pain_target(string) : "Fire this target when pain_threshold is reached"
pain_threshold(integer) : "Fire pain_target when health drops below this amount"
sight_trigger(integer) : "1 = Fire target upon seeing the player instead of death"
skin(integer) : "Skin index (default 0) Use this when your custom model has more than one skin to select"
obit_name(string) : "When used with obit_method, this will set part of the text for a custom obituary. e.g. a Super Soldier! Using the examples here, the obituary would read: Player was eviscerated by a Super Solider!"
obit_method(string) : "When used with obit_name, will set part of the text for a custom obituary. e.g. eviscerated - If empty, defaults to killed."
damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by this number (e.g. 4 = Quad damage)"

*/
//----------------------------------------------------------------------
// class monster_demon1: base_walkmonster
// {
//--------------------------------------------------------------
// CheckDemonMelee
// Returns TRUE if a melee attack would hit right now
//--------------------------------------------------------------
/*
float() monster_demon1_checkmelee =
{
if (enemy_range == RANGE_MELEE)
{
// FIXME: check canreach
self.attack_state = AS_MELEE;
return TRUE;
}
return FALSE;
};
*/

//--------------------------------------------------------------
// CheckDemonJump
//--------------------------------------------------------------
float() monster_demon1_checkjump =
{
local vector dist;
local float d;

if (self.origin_z + self.mins_z >
self.enemy.origin_z + self.enemy.mins_z +
0.75 * self.enemy.size_z)
{
return FALSE;
}

if (self.origin_z + self.maxs_z <
self.enemy.origin_z + self.enemy.mins_z +
0.25 * self.enemy.size_z)
{
return FALSE;
}

dist = self.enemy.origin - self.origin;
dist_z = 0;

d = vlen (dist);

if (d < 100)
return FALSE;

if (d > 200)
{
if (random() < 0.9)
return FALSE;
}

return TRUE;
};

//--------------------------------------------------------------
// DemonCheckAttack
//--------------------------------------------------------------
float() monster_demon1_checkattack =
{
// if close enough for slashing, go for it
// if (CheckDemonMelee())
if (enemy_range == RANGE_MELEE)
{
self.attack_state = AS_MELEE;
return TRUE;
}

if (monster_demon1_checkjump())
{
self.attack_state = AS_MISSILE;
sound_attack (self, CHAN_VOICE, "demon/djump.wav",
1, ATTN_NORM);
return TRUE;
}

return FALSE;
};

//--------------------------------------------------------------
void() monster_demon1_sightsound =
{
sound_sight (self, CHAN_VOICE, "demon/sight2.wav",
1, ATTN_NORM);
};

//--------------------------------------------------------------
void(float side) monster_demon1_melee =
{
local float ldmg;
local vector delta;

ai_face ();
// allow a little closing
walkmove (self.ideal_yaw, 12);

delta = self.enemy.origin - self.origin;

if (vlen(delta) > 100)
return;
if (!can_damage(self, self.enemy))
return;

sound_hit (self, CHAN_WEAPON, "demon/dhit2.wav", 1, ATTN_NORM);
ldmg = 10 + 5 * random ();
t_damage2 (self.enemy, self, self, ldmg);

makevectors (self.angles);
spawn_meatspray (self.origin + v_forward * 16, side * v_right);
};

//--------------------------------------------------------------
// Fiend stand functions
//--------------------------------------------------------------
void() dem1_stand1 = [$stand1, dem1_stand2] { ai_stand (); };
void() dem1_stand2 = [$stand2, dem1_stand3] { ai_stand (); };
void() dem1_stand3 = [$stand3, dem1_stand4] { ai_stand (); };
void() dem1_stand4 = [$stand4, dem1_stand5] { ai_stand (); };
void() dem1_stand5 = [$stand5, dem1_stand6] { ai_stand (); };
void() dem1_stand6 = [$stand6, dem1_stand7] { ai_stand (); };
void() dem1_stand7 = [$stand7, dem1_stand8] { ai_stand (); };
void() dem1_stand8 = [$stand8, dem1_stand9] { ai_stand (); };
void() dem1_stand9 = [$stand9, dem1_stand10] { ai_stand (); };
void() dem1_stand10 = [$stand10, dem1_stand11] { ai_stand (); };
void() dem1_stand11 = [$stand11, dem1_stand12] { ai_stand (); };
void() dem1_stand12 = [$stand12, dem1_stand13] { ai_stand (); };
void() dem1_stand13 = [$stand13, dem1_stand1] { ai_stand (); };

//--------------------------------------------------------------
// Fiend walk functions
//--------------------------------------------------------------
void() dem1_walk1 = [$walk1, dem1_walk2]
{
if (random() < 0.2)
sound_idle (self, CHAN_VOICE, "demon/idle1.wav",
1, ATTN_IDLE);
ai_walk (8);
};
void() dem1_walk2 = [$walk2, dem1_walk3] { ai_walk (6); };
void() dem1_walk3 = [$walk3, dem1_walk4] { ai_walk (6); };
void() dem1_walk4 = [$walk4, dem1_walk5] { ai_walk (7); };
void() dem1_walk5 = [$walk5, dem1_walk6] { ai_walk (4); };
void() dem1_walk6 = [$walk6, dem1_walk7] { ai_walk (6); };
void() dem1_walk7 = [$walk7, dem1_walk8] { ai_walk (10); };
void() dem1_walk8 = [$walk8, dem1_walk1] { ai_walk (10); };

//--------------------------------------------------------------
// Fiend run functions
//--------------------------------------------------------------
void() dem1_run1 = [$run1, dem1_run2]
{
if (random() < 0.2)
sound_idle (self, CHAN_VOICE, "demon/idle1.wav",
1, ATTN_IDLE);
ai_run (20);
};
void() dem1_run2 = [$run2, dem1_run3] { ai_run (15); };
void() dem1_run3 = [$run3, dem1_run4] { ai_run (36); };
void() dem1_run4 = [$run4, dem1_run5] { ai_run (20); };
void() dem1_run5 = [$run5, dem1_run6] { ai_run (15); };
void() dem1_run6 = [$run6, dem1_run1] { ai_run (36); };

//--------------------------------------------------------------
// Fiend jump functions
//--------------------------------------------------------------
void() dem1_jump1 = [$leap1, dem1_jump2] { ai_face (); };
void() dem1_jump2 = [$leap2, dem1_jump3] { ai_face (); };
void() dem1_jump3 = [$leap3, dem1_jump4] { ai_face (); };
void() dem1_jump4 = [$leap4, dem1_jump5]
{
ai_face ();
// fix for instakill bug -- dumptruck_ds
self.worldtype = 0;
self.touch = monster_demon1_touch;
makevectors (self.angles);
self.origin_z = self.origin_z + 1;
self.velocity = v_forward * 600 + '0 0 250';
if (self.flags & FL_ONGROUND)
self.flags = self.flags - FL_ONGROUND;
};
void() dem1_jump5 = [$leap5, dem1_jump6] {};
void() dem1_jump6 = [$leap6, dem1_jump7] {};
void() dem1_jump7 = [$leap7, dem1_jump8] {};
void() dem1_jump8 = [$leap8, dem1_jump9] {};
void() dem1_jump9 = [$leap9, dem1_jump10] {};
void() dem1_jump10 = [$leap10, dem1_jump1]
{
// if three seconds pass, assume demon is stuck and jump again
self.nextthink = time + 3;
};
void() dem1_jump11 = [$leap11, dem1_jump12] {};
void() dem1_jump12 = [$leap12, dem1_run1] {};

//--------------------------------------------------------------
// Fiend attack functions
//--------------------------------------------------------------
void() dem1_atk1 = [$attacka1, dem1_atk2] { ai_charge (4); };
void() dem1_atk2 = [$attacka2, dem1_atk3] { ai_charge (0); };
void() dem1_atk3 = [$attacka3, dem1_atk4] { ai_charge (0); };
void() dem1_atk4 = [$attacka4, dem1_atk5] { ai_charge (1); };
void() dem1_atk5 = [$attacka5, dem1_atk6]
{
ai_charge (2);
monster_demon1_melee (200);
};
void() dem1_atk6 = [$attacka6, dem1_atk7] { ai_charge (1); };
void() dem1_atk7 = [$attacka7, dem1_atk8] { ai_charge (6); };
void() dem1_atk8 = [$attacka8, dem1_atk9] { ai_charge (8); };
void() dem1_atk9 = [$attacka9, dem1_atk10] { ai_charge (4); };
void() dem1_atk10 = [$attacka10, dem1_atk11] { ai_charge (2); };
void() dem1_atk11 = [$attacka11, dem1_atk12]
{
monster_demon1_melee (-200);
};
void() dem1_atk12 = [$attacka12, dem1_atk13] { ai_charge (5); };
void() dem1_atk13 = [$attacka13, dem1_atk14] { ai_charge (8); };
void() dem1_atk14 = [$attacka14, dem1_atk15] { ai_charge (4); };
void() dem1_atk15 = [$attacka15, dem1_run1] { ai_charge (4); };

//--------------------------------------------------------------
// Fiend pain states
//--------------------------------------------------------------
void() dem1_pain1 = [$pain1, dem1_pain2] { };
void() dem1_pain2 = [$pain2, dem1_pain3] { };
void() dem1_pain3 = [$pain3, dem1_pain4] { };
void() dem1_pain4 = [$pain4, dem1_pain5] { };
void() dem1_pain5 = [$pain5, dem1_pain6] { };
void() dem1_pain6 = [$pain6, dem1_run1] { };

//--------------------------------------------------------------
// Fiend death states
//--------------------------------------------------------------
void() dem1_die1 = [$death1, dem1_die2]
{
sound_death (self, CHAN_VOICE, "demon/ddeath.wav",
1, ATTN_NORM);
};
void() dem1_die2 = [$death2, dem1_die3] { };
void() dem1_die3 = [$death3, dem1_die4] { };
void() dem1_die4 = [$death4, dem1_die5] { };
void() dem1_die5 = [$death5, dem1_die6] { };
void() dem1_die6 = [$death6, dem1_die7]
{
self.solid = SOLID_NOT;
};
void() dem1_die7 = [$death7, dem1_die8] { };
void() dem1_die8 = [$death8, dem1_die9] { };
void() dem1_die9 = [$death9, dem1_die9] { };

//==============================================================
// Interaction
//==============================================================

//--------------------------------------------------------------
void(entity attacker, float damage) monster_demon1_pain =
{
if (self.touch == monster_demon1_touch)
return;

if (self.pain_finished > time)
return;

self.pain_finished = time + 1;
sound_pain (self, CHAN_VOICE, "demon/dpain1.wav", 1, ATTN_NORM);

if (random() * 200 > damage)
// didn't flinch
return;

dem1_pain1 ();
};

//--------------------------------------------------------------
void(vector dir) monster_demon1_destroy =
{
// check for gib
if (self.health < -80)
{
sound (self, CHAN_VOICE, "player/udeath.wav",
1, ATTN_NORM);

throw_gib_head_demon (self, dir, self.health);

// TODO CEV this doesn't work *quite* right
throw_gib_1 (self, dir, self.health);

// custom models -- dumptruck_ds
if (self.mdl_gib2 != "")
throw_gib_2 (self, dir, self.health);
else
throw_gib_1 (self, dir, self.health);

if (self.mdl_gib3 != "")
throw_gib_3 (self, dir, self.health);
else
throw_gib_1 (self, dir, self.health);

base_item_drop_stuff (self);
return;
}

// regular death
base_item_drop_stuff (self);
dem1_die1 ();
};

//--------------------------------------------------------------
// Demon_JumpTouch
//--------------------------------------------------------------
void() monster_demon1_touch =
{
local float ldmg;

if (self.health <= 0)
return;

if (other.takedamage)
{
if (vlen(self.velocity) > 400)
{
if !(self.worldtype)
{
ldmg = 40 + 10 * random();
t_damage2 (other, self, self, ldmg);
// is the player still alive?
// Preach's instakill bug check
// - dumptruck_ds
if (other.health > 0)
self.worldtype = 1;
}
}
}

if (!checkbottom(self))
{
if (self.flags & FL_ONGROUND)
{
// jump randomly to not get hung up
// dprint ("popjump\n");
// 1998-09-16 Sliding/not-jumping on monsters/
// boxes/players fix by Maddes/Kryten start
self.touch = base_monster_touch;
// 1998-09-16 Sliding/not-jumping on monsters/
// boxes/players fix by Maddes/Kryten end
self.think = dem1_jump1;
self.nextthink = time + 0.1;

// self.velocity_x = (random() - 0.5) * 600;
// self.velocity_y = (random() - 0.5) * 600;
// self.velocity_z = 200;
// self.flags = self.flags - FL_ONGROUND;
}
// not on ground yet
return;
}

// 1998-09-16 Sliding/not-jumping on monsters/boxes/players
// fix by Maddes/Kryten start
self.touch = base_monster_touch;
// 1998-09-16 Sliding/not-jumping on monsters/boxes/players
// fix by Maddes/Kryten end
self.think = dem1_jump11;
self.nextthink = time + 0.1;
};

//==============================================================
// Initialization
//==============================================================

//--------------------------------------------------------------
void(entity e) monster_demon1_init =
{
if (e.spawnflags & I_AM_TURRET)
objerror ("Incompatible spawnflag: TURRET_MODE\n");

if (deathmatch)
{
remove (e);
return;
}

e.classname = "monster_demon1";
e.classtype = CT_MONSTER_FIEND;

// dumptruck_ds custom_mdls
precache_body_model (e, "progs/demon.mdl");
precache_head_model (e, "progs/h_demon.mdl");

precache_sound_death (e, "demon/ddeath.wav");
precache_sound_hit (e, "demon/dhit2.wav");
precache_sound_attack (e, "demon/djump.wav");
precache_sound_pain (e, "demon/dpain1.wav");
precache_sound_idle (e, "demon/idle1.wav");
precache_sound_sight (e, "demon/sight2.wav");

precache_gib1 (e, "progs/gib1.mdl");
// precache_gib2 ("progs/gib2.mdl");
// precache_gib3 ("progs/gib3.mdl");

e.solid = SOLID_SLIDEBOX;
e.movetype = MOVETYPE_STEP;

body_model (e, "progs/demon.mdl");
// setmodel (e, "progs/demon.mdl");

setsize (e, VEC_HULL2_MIN, VEC_HULL2_MAX);

if (!e.health)
// thanks RennyC -- dumptruck_ds
e.health = DEMON1_HEALTH;

e.checkattack = monster_demon1_checkattack;
e.sightsound = monster_demon1_sightsound;
e.think_stand = dem1_stand1;
e.think_walk = dem1_walk1;
e.think_run = dem1_run1;
// two attacks: melee, jump
// e.think_melee = Demon_MeleeAttack;
e.think_melee = dem1_atk1;
e.think_missile = dem1_jump1;

// Berserk test from
// http://celephais.net/board/view_thread.php?id=4&start=3465
// -- dumptruck_ds
if !(e.berserk)
e.pain = monster_demon1_pain;
else
e.pain = sub_nullpain;

e.destroy = monster_demon1_destroy;

// walkmonster_start
base_walkmonster_init (e);
};

//--------------------------------------------------------------
void() monster_demon1 =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

monster_demon1_init (self);
};
// };

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

/*QUAKED gib_head_demon (0 0.5 0.8) (-16 -16 0) (16 16 56) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ("progs/h_demon.mdl");
}
*/
//----------------------------------------------------------------------
// class gib_head_demon: base_gib_head
// {
//--------------------------------------------------------------
// ThrowHead
//--------------------------------------------------------------
void(entity act, vector dir, float dmg) throw_gib_head_demon =
{
base_gib_head_throw (act, dir, dmg, gib_head_demon_init);
};

//--------------------------------------------------------------
void(entity e) gib_head_demon_init =
{
e.classname = "gib_head_demon";
e.classtype = CT_GORE_HEAD_DEMON;

// gib_init interprets spawnflags and will set .solid -- CEV
base_gib_head_init (e);

if (e.mdl_head != "")
{
precache_model (e.mdl_head);
setmodel (e, e.mdl_head);
}
else
{
precache_model ("progs/h_demon.mdl");
setmodel (e, "progs/h_demon.mdl");
if (e.solid == SOLID_BBOX)
setsize (e, DEMON1_HEAD_MINS, DEMON1_HEAD_MAXS);
else if (e.solid == SOLID_TRIGGER)
setsize (e, '-16 -16 0', '16 16 56');
}

e.frame = 0;
};

//--------------------------------------------------------------
void() gib_head_demon =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

gib_head_demon_init (self);
};
// };

/*QUAKED monster_dead_demon (0 0.5 0.8) (-32 -32 -24) (32 32 64) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ({"path":"progs/demon.mdl","frame":53});
}
*/
void() monster_dead_demon =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

precache_model ("progs/demon.mdl");
setmodel (self, "progs/demon.mdl");
self.frame = $death9;
if (self.spawnflags & 1)
{
self.solid = SOLID_BBOX;
setsize (self,'-43.63 -47.26 -50.53','32.48 24.65 30');
}
else
{
self.solid = SOLID_NOT;
}
};

Return to the top of this page or return to the overview of this repo.

Log demon.qc

Date Commit Message Author + -
2024-04-12 Moveable gibs, heads, some bugfixes cev +80 -21
2024-04-05 Player footsteps, shareware monsters, misc? cev +273 -250
2024-02-18 Client/player, projectiles, entrypoints refactor cev +4 -4
2024-01-31 Class based monster refactor & start projectiles cev +451 -362
2024-01-13 Refactored items into classes, fix teleporttrain cev +3 -2
2024-01-09 Continue OO / Class-based refactor cev +3 -3
2023-10-13 New movement code based on SV_RunClientCommand cev +502 -502
2023-10-13 Rename "qc-server" dir to "qc" cev +502  

Return to the top of this page or return to the overview of this repo.