1#include "playerdemo.qh"
2#if defined(CSQC)
3#elif defined(MENUQC)
4#elif defined(SVQC)
5    #include "defs.qh"
6    #include "playerdemo.qh"
7#endif
8
9.float playerdemo_fh;
10.float playerdemo_mode;
11.float playerdemo_starttime;
12.float playerdemo_time;
13const float PLAYERDEMO_MODE_OFF = 0;
14const float PLAYERDEMO_MODE_READING = 1;
15const float PLAYERDEMO_MODE_WRITING = 2;
16void playerdemo_init(entity this)
17{
18	this.playerdemo_mode = PLAYERDEMO_MODE_OFF;
19}
20void playerdemo_shutdown(entity this)
21{
22	if(this.playerdemo_mode != PLAYERDEMO_MODE_OFF)
23	{
24		LOG_INFO("playerdemo: ", this.netname, " closed\n");
25		fclose(this.playerdemo_fh);
26	}
27	this.playerdemo_mode = 0;
28}
29void playerdemo_open_read(entity this, string f)
30{
31	playerdemo_shutdown(this);
32	this.playerdemo_mode = PLAYERDEMO_MODE_READING;
33	this.playerdemo_fh = fopen(f, FILE_READ);
34	this.playerdemo_starttime = time - 1;
35	this.playerdemo_time = stof(fgets(this.playerdemo_fh));
36	this.playerdemo_time += this.playerdemo_starttime;
37	set_movetype(this, MOVETYPE_NONE);
38	LOG_INFO("playerdemo: ", this.netname, " reading from ", f, "\n");
39}
40void playerdemo_open_write(entity this, string f)
41{
42	playerdemo_shutdown(this);
43	this.playerdemo_mode = PLAYERDEMO_MODE_WRITING;
44	this.playerdemo_fh = fopen(f, FILE_WRITE);
45	this.playerdemo_starttime = time - 1;
46	LOG_INFO("playerdemo: ", this.netname, " writing to ", f, "\n");
47	LOG_INFO("WARNING: playerdemo file format is incomplete and not stable yet. DO NOT RELY ON IT!\n");
48}
49#define PLAYERDEMO_FIELD(ent,func,t,f) func##t(ent,f,#f);
50#define PLAYERDEMO_FIELDS(ent,func) \
51	PLAYERDEMO_FIELD(ent,func,originvector,origin) \
52	PLAYERDEMO_FIELD(ent,func,vector,angles) \
53	PLAYERDEMO_FIELD(ent,func,sizevector,mins) \
54	PLAYERDEMO_FIELD(ent,func,sizevector,maxs) \
55	PLAYERDEMO_FIELD(ent,func,vector,v_angle) \
56	PLAYERDEMO_FIELD(ent,func,modelstring,model) \
57	PLAYERDEMO_FIELD(ent,func,string,playermodel) \
58	PLAYERDEMO_FIELD(ent,func,float,skin) \
59	PLAYERDEMO_FIELD(ent,func,string,playerskin) \
60	PLAYERDEMO_FIELD(ent,func,float,frame) \
61	PLAYERDEMO_FIELD(ent,func,float,effects) \
62	/* PLAYERDEMO_FIELD(ent,func,float,switchweapon) */ \
63	PLAYERDEMO_FIELD(ent,func,float,button0) /* TODO: PHYS_INPUT_BUTTON_ATCK */ \
64	PLAYERDEMO_FIELD(ent,func,float,button3) /* TODO: PHYS_INPUT_BUTTON_ATCK2 */ \
65	PLAYERDEMO_FIELD(ent,func,float,button5) /* TODO: PHYS_INPUT_BUTTON_CROUCH */ \
66	PLAYERDEMO_FIELD(ent,func,float,button6) /* TODO: PHYS_INPUT_BUTTON_HOOK */ \
67	PLAYERDEMO_FIELD(ent,func,float,buttonuse) /* TODO: PHYS_INPUT_BUTTON_USE */ \
68	PLAYERDEMO_FIELD(ent,func,float,flags) \
69	// end of list
70
71void playerdemo_write_originvector(entity this, .vector f, string name)
72{
73	fputs(this.playerdemo_fh, strcat(vtos(this.(f)), "\n"));
74}
75void playerdemo_write_sizevector(entity this, .vector f, string name)
76{
77	fputs(this.playerdemo_fh, strcat(vtos(this.(f)), "\n"));
78}
79void playerdemo_write_vector(entity this, .vector f, string name)
80{
81	fputs(this.playerdemo_fh, strcat(vtos(this.(f)), "\n"));
82}
83void playerdemo_write_string(entity this, .string f, string name)
84{
85	fputs(this.playerdemo_fh, strcat(this.(f), "\n"));
86}
87void playerdemo_write_modelstring(entity this, .string f, string name)
88{
89	fputs(this.playerdemo_fh, strcat(this.(f), "\n"));
90}
91void playerdemo_write_float(entity this, .float f, string name)
92{
93	fputs(this.playerdemo_fh, strcat(ftos(this.(f)), "\n"));
94}
95void playerdemo_write(entity this)
96{
97	if(this.playerdemo_mode != PLAYERDEMO_MODE_WRITING)
98		return;
99	fputs(this.playerdemo_fh, strcat(ftos(time - this.playerdemo_starttime), "\n"));
100	PLAYERDEMO_FIELDS(this, playerdemo_write_)
101}
102void playerdemo_read_originvector(entity this, .vector f, string name)
103{
104	setorigin(this, stov(fgets(this.playerdemo_fh)));
105}
106void playerdemo_read_sizevector(entity this, .vector f, string name)
107{
108	this.(f) = stov(fgets(this.playerdemo_fh));
109	setsize(this, this.mins, this.maxs);
110}
111void playerdemo_read_vector(entity this, .vector f, string name)
112{
113	this.(f) = stov(fgets(this.playerdemo_fh));
114}
115void playerdemo_read_string(entity this, .string f, string name)
116{
117	string s = fgets(this.playerdemo_fh);
118	if (s != this.(f))
119	{
120		/*
121		if(this.f)
122			strunzone(this.f);
123		*/
124		this.(f) = strzone(s);
125	}
126}
127void playerdemo_read_modelstring(entity this, .string f, string name)
128{
129	string s = fgets(this.playerdemo_fh);
130	if (s != this.(f))
131		_setmodel(this, s);
132}
133void playerdemo_read_float(entity this, .float f, string name)
134{
135	this.(f) = stof(fgets(this.playerdemo_fh));
136}
137float playerdemo_read(entity this)
138{
139	if(this.playerdemo_mode != PLAYERDEMO_MODE_READING)
140		return 0;
141	if(this.playerdemo_time < 0)
142		return 1;
143	float t;
144	t = time;
145	while(time >= this.playerdemo_time)
146	{
147		PLAYERDEMO_FIELDS(this, playerdemo_read_)
148		{
149			time = this.playerdemo_time;
150			PlayerPreThink(this);
151			// not running physics though... this is just so we can run weapon stuff
152			PlayerPostThink(this);
153		}
154		this.playerdemo_time = stof(fgets(this.playerdemo_fh));
155		if(this.playerdemo_time == 0)
156		{
157			this.playerdemo_time = -1;
158			return 1;
159		}
160		this.playerdemo_time += this.playerdemo_starttime;
161	}
162	this.velocity = '0 0 0';
163	time = t;
164	return 1;
165}
166