hexen2/H2MP/hcode/t_head.hc
2000-11-10 00:00:00 +00:00

570 lines
14 KiB
C++

$frame idle1 idle2 idle3 idle4 idle5
$frame idle6 idle7 idle8 idle9 idle10
$frame idle11 idle12 idle13 idle14 idle15
$frame idle16 idle17 idle18 idle19 idle20
$frame idle21 idle22 idle23 idle24 idle25
$frame idle26 idle27 idle28 idle29 idle30
$frame speak1 speak2 speak3 speak4 speak5
$frame speak6 speak7 speak8 speak9 speak10
$frame speak11 speak12 speak13 speak14 speak15
$frame speak16 speak17 speak18 speak19 speak20
/*
Talkin' Heads
Heads that can speak to you- triggered by events. Can
play a series of sound files mixed in with delays. Designer
needs to be able to script the list of sound files in order
with a specified delay for each. Also needs to support
multiple triggerable events. (Trigger Relay Event?)
PROBLEM: Need to be able to have entity fields that are
arrays of 256 floats (max number of sound events) so that
their values can be set by the designer in the map file.
NOTA BENE: talking heads must not use any of these fields... (in struct)
float splash_time; // When to generate the next splash
float camera_time; //
float weaponframe_cnt; //
float attack_cnt; // Shows which attack animation can be used
float ring_regen_time; // When to add the next point of health
float ring_flight_time; // When to update ring of flight health
float ring_water_time; // When to update ring of waterbreathing health
float ring_turning_time;// When to update ring of turning health
float super_damage; // Player does this much more damage (Like Crusader with Special Ability #2)
float super_damage_low; // Flag the super damage is low
float puzzles_cheat; // Allows player past puzzle triggers
float camptime; // Amount of time player has been motionless
float crouch_time; // Next time player should run crouch subroutine
float crouch_stuck; // If set this means the player has released the crouch key in an area too small to uncrouch in
float divine_time; // Amount of time flash happens in divine intervention
float act_state; // Anim info
float raven_cnt; // Number of raven's this guys has in the world
float newclass; // If doing a quick class change
float fangel_SaveFrame;
float fangel_Count;
float shoot_cnt;
float shoot_time; // Time of last shot
float z_movement;
float z_duration;
float drop_time;
float spell_angle;
float hydra_FloatTo;
float hydra_chargeTime;
float spiderType; // SPIDER_? types
float spiderActiveCount; // Tallies "activity"
float spiderGoPause; // Active/pause threshold
float spiderPauseLength; // Pause duration in frames
float spiderPauseCount; // Tallies paused frames
float scorpionType; // SCORPION_? types
float scorpionRest; // Resting state counter
float scorpionWalkCount; // Counts walking frames
float golemSlideCounter;
float golemBeamDelay;
float golemBeamOff1;
float golemBeamOff2;
float impType; // IMP_? types
float parts_gone;
float mummy_state;
float mummy_state_time;
float artifact_respawn; // Should respawn?
float artifact_ignore_owner_time;
float artifact_ignore_time;
float next_path_1;
float next_path_2;
float next_path_3;
float next_path_4;
float path_id;
float next_path_5;
float next_path_6;
float rt_chance;
float rider_gallop_mode;
float rider_last_y_change;
float rider_y_change;
float rider_death_speed;
float rider_path_distance;
float rider_move_adjustment;
float waraxe_offset;
float waraxe_horizontal;
float waraxe_track_inc;
float waraxe_track_limit;
float waraxe_max_speed;
float waraxe_max_height;
float wrq_effect_id;
float wrq_radius;
float wrq_count;
float beam_angle_a;
float beam_angle_b;
float beam_max_scale;
float beam_direction;
float beam_speed;
float z_modifier;
float last_health; // Used by bell entity
float idealpitch;
float pitchdowntime;
float searchtime; // Amount of time bird has been searching
float next_action; // Next time to take action
float searchtime; // When search was first started
float damage_max; // Amount of damage each raven can do before it has to leave
float fish_speed;
float fish_leader_count;
float exploderadius;
float scream_time;
float attack_cnt;
float beginframe;
float sound_time;
float shot_cnt; // Number of shots the force cube has shot
*/
/*
Voice filename and length arrays.
*/
void()talkhead_speak_init;
float voice_slot (float vs)
{
switch(vs)
{
case 1:
return self.voice1;
break;
case 2:
return self.voice2;
break;
case 3:
return self.voice3;
break;
case 4:
return self.voice4;
break;
case 5:
return self.voice5;
break;
case 6:
return self.voice6;
break;
case 7:
return self.voice7;
break;
case 8:
return self.voice8;
break;
case 9:
return self.voice9;
break;
case 10:
return self.voice10;
break;
default:
dprint("Voice Slot out of limits!\n");
return 0;
break;
}
}
float delay_slot (float ds)
{
switch(ds)
{
case 1:
return self.delay1;
break;
case 2:
return self.delay2;
break;
case 3:
return self.delay3;
break;
case 4:
return self.delay4;
break;
case 5:
return self.delay5;
break;
case 6:
return self.delay6;
break;
case 7:
return self.delay7;
break;
case 8:
return self.delay8;
break;
case 9:
return self.delay9;
break;
case 10:
return self.delay10;
break;
default:
dprint("Delay Slot out of limits!\n");
return 0;
break;
}
}
string voice_filename (float sf_index)
{//Can't have an array of strings
switch(sf_index)
{
case 1:
return "t_heads/hey.wav"; //"Hey!"
break;
case 2:
return "t_heads/you.wav"; //"You!"
break;
case 3:
return "t_heads/overhere.wav"; //"Over here!"
break;
case 4:
return "t_heads/halt1.wav";
break;
case 5:
return "t_heads/chat7b.wav";
break;
default:
return "t_heads/default.wav";
break;
}
}
float voice_length [51] =
{//Need to know how long sound is to stop mouth movement and start delay
0, //Null first sound
2.610, //hey!
2.659, //you!
2.522, //over here!
0.530, //halt!
2.500, //DeutcheSprach
0.523, //default
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1
};
void talkhead_idle () [++$idle1 .. $idle30]
{
if(self.frame==$idle1)
dprint("T_head idle\n");
}
void obj_talkinghead ()
{
float cnter, voicenumber;
string voicestring;
if(self.health>0)
self.takedamage=TRUE;
self.classname="obj_talkinghead";
self.thingtype=THINGTYPE_FLESH;
self.solid=SOLID_BBOX;
self.movetype=MOVETYPE_NONE;//?
self.use=talkhead_speak_init;
self.th_die=chunk_death;//death sound? Scream?
cnter=1;
while(voice_slot(cnter)>0&&cnter<11)
{//Precache all the sounds
dprint("t_head precaching\n");
voicenumber=voice_slot(cnter);
voicestring=voice_filename(voicenumber);
precache_sound(voicestring);
cnter+=1;
}
dprint("T_head done precaching\n");
//do they have idle anims?
self.think=talkhead_idle;
thinktime self : self.wait;
}
/*QUAKED obj_talkinghead1 (0.3 0.1 0.6) (-12 -12 -32) (12 12 0)
Note: Origin is at top of head where it hangs from ceiling
health = how many hp it has. <=0 means it can't be shot and broken. Still can be destroyed by a .killtarget field.
voice1 - voice10: "-1" = loop back at start. -# will go back to the positive value of that number.
delay1 - delay10: "-1" = stop forever, 0 = wait for next trigger, >0 = wait this long before next sound
loop = number of times to loop
NOTE: no next voice (0) and no next delay (0) will make it wait for a trigger event and start all over again from the beginning of the list
EXAMPLE:
voice1 = 1 //play sound 1
delay1 = 1 //wait 1 second
voice2 = 10 //play sound 10
delay2 = 3 //wait 1 second
voice3 = 17 //play sound 17
//!! NOTE: no value (0) for delay3 means to wait until it's triggered again to continue. If there WERE no .voice[4] value(0), it would just start back at the beginning on the next triggering.
//a -1 value in a delay will make it not be triggerable again after this point
//Next triggering:
voice4 = 22 //play sound 22
delay4 = 2 //wait 2 seconds
voice5 = 13 //play sound 13
delay5 = 2 //wait 2 seconds
voice6 = -2 //Tells it to go back to voice2
loop = 3 //repeat loop 3 times before moving on
delay6 = 1 //after last loop finished, wait 1 second and continue. A zero value here would make it wait for the next triggering to continue
voice7 = 4 //play sound 4
delay7 = -1 //Stop here and never trigger again
resultant sound sequence:
1
10
17
wait for trigger
22
13
10 (start first loop)
17
wait for trigger
22
13
10 (start second loop)
17
wait for trigger
22
13
10 (start third loop)
17
wait for trigger
22
13
4
stop forever
*/
void obj_talkinghead1 ()
{
precache_model2("models/t_head1.mdl");
setmodel(self,"models/t_head1.mdl");
obj_talkinghead();
}
/*QUAKED obj_talkinghead2 (0.3 0.1 0.6) (-12 -12 -32) (12 12 0)
Note: Origin is at top of head where it hangs from ceiling
health = how many hp it has. <=0 means it can't be shot and broken. Still can be destroyed by a .killtarget field.
voice1 - voice10: "-1" = loop back at start. -# will go back to the positive value of that number.
delay1 - delay10: "-1" = stop forever, 0 = wait for next trigger, >0 = wait this long before next sound
loop = number of times to loop
NOTE: no next voice (0) and no next delay (0) will make it wait for a trigger event and start all over again from the beginning of the list
EXAMPLE:
voice1 = 1 //play sound 1
delay1 = 1 //wait 1 second
voice2 = 10 //play sound 10
delay2 = 3 //wait 1 second
voice3 = 17 //play sound 17
//!! NOTE: no value (0) for delay3 means to wait until it's triggered again to continue. If there WERE no .voice[4] value(0), it would just start back at the beginning on the next triggering.
//a -1 value in a delay will make it not be triggerable again after this point
//Next triggering:
voice4 = 22 //play sound 22
delay4 = 2 //wait 2 seconds
voice5 = 13 //play sound 13
delay5 = 2 //wait 2 seconds
voice6 = -2 //Tells it to go back to voice2
loop = 3 //repeat loop 3 times before moving on
delay6 = 1 //after last loop finished, wait 1 second and continue. A zero value here would make it wait for the next triggering to continue
voice7 = 4 //play sound 4
delay7 = -1 //Stop here and never trigger again
resultant sound sequence:
1
10
17
wait for trigger
22
13
10 (start first loop)
17
wait for trigger
22
13
10 (start second loop)
17
wait for trigger
22
13
10 (start third loop)
17
wait for trigger
22
13
4
stop forever
*/
void obj_talkinghead2 ()
{
precache_model2("models/t_head2.mdl");
setmodel(self,"models/t_head2.mdl");
obj_talkinghead();
}
/*QUAKED obj_talkinghead3 (0.3 0.1 0.6) (-12 -12 -32) (12 12 0)
Note: Origin is at top of head where it hangs from ceiling
health = how many hp it has. <=0 means it can't be shot and broken. Still can be destroyed by a .killtarget field.
voice1 - voice10: "-1" = loop back at start. -# will go back to the positive value of that number.
delay1 - delay10: "-1" = stop forever, 0 = wait for next trigger, >0 = wait this long before next sound
loop = number of times to loop
NOTE: no next voice (0) and no next delay (0) will make it wait for a trigger event and start all over again from the beginning of the list
EXAMPLE:
voice1 = 1 //play sound 1
delay1 = 1 //wait 1 second
voice2 = 10 //play sound 10
delay2 = 3 //wait 1 second
voice3 = 17 //play sound 17
//!! NOTE: no value (0) for delay3 means to wait until it's triggered again to continue. If there WERE no .voice[4] value(0), it would just start back at the beginning on the next triggering.
//a -1 value in a delay will make it not be triggerable again after this point
//Next triggering:
voice4 = 22 //play sound 22
delay4 = 2 //wait 2 seconds
voice5 = 13 //play sound 13
delay5 = 2 //wait 2 seconds
voice6 = -2 //Tells it to go back to voice2
loop = 3 //repeat loop 3 times before moving on
delay6 = 1 //after last loop finished, wait 1 second and continue. A zero value here would make it wait for the next triggering to continue
voice7 = 4 //play sound 4
delay7 = -1 //Stop here and never trigger again
resultant sound sequence:
1
10
17
wait for trigger
22
13
10 (start first loop)
17
wait for trigger
22
13
10 (start second loop)
17
wait for trigger
22
13
10 (start third loop)
17
wait for trigger
22
13
4
stop forever
*/
void obj_talkinghead3 ()
{
precache_model2("models/t_head3.mdl");
setmodel(self,"models/t_head3.mdl");
obj_talkinghead();
}
void talkhead_speaking () [++ $speak1 .. $speak20]
{
if(time>=self.wait)
if(delay_slot(self.cnt)>0)
{
self.think=talkhead_speak_init;
thinktime self : delay_slot(self.cnt);
}
else
{//0 will make it wait to be triggered again- you can continue a list of words afterwards
if(delay_slot(self.cnt)==-1)
self.use=SUB_Null;//stop forever
else if(voice_slot(self.cnt+1)==0)//No next voice!
self.cnt=0;//Start over from beginning
if(delay_slot(self.cnt)==0)
{//Done witrh this trigger, go back to idle anim
self.think=talkhead_idle;
thinktime self : 0;
}
else
{//Just pausing between words
self.frame=$idle1;//Root frame
self.think=SUB_Null;
self.nextthink=-1;
}
}
}
void talkhead_speak_init ()
{//FIX ME: WHAT IF TALKING AND USED AGAIN- INTERRUPT?
dprint("Being used!\n");
self.cnt+=1;
if(voice_slot(self.cnt)<0)//A loop value
if(self.loop>0)//still have loops left to do
{
self.cnt=voice_slot(self.cnt) * -1;//go to loop voice value
self.loop-=1;//subtract one loop
}
else
{
if(voice_slot(self.cnt+1)!=0)
self.cnt+=1;//Go onto next sequence, finished all loops
else
{//No next voice, so wait to trigger again
if(delay_slot(self.cnt)==-1)//Next delay is -1
self.use=SUB_Null;//stop forever
else
self.cnt=0;//Start over from the beginning
self.think=SUB_Null;//or go to idle anim?
self.nextthink=-1;
return;
}
}
sound(self,CHAN_VOICE,voice_filename(voice_slot(self.cnt)),1,ATTN_NORM);
self.think=talkhead_speaking;
thinktime self : 0;
self.wait=time+voice_length[voice_slot(self.cnt)];
}