source: abuse/trunk/src/demo.cpp @ 643

Last change on this file since 643 was 643, checked in by Sam Hocevar, 11 years ago

imlib: refactor Event and EventHandler?.

File size: 6.4 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com, by
8 *  Jonathan Clark, or by Sam Hocevar.
9 */
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include "common.h"
16
17#include "game.h"
18
19#include "demo.h"
20#include "specs.h"
21#include "jwindow.h"
22#include "dprint.h"
23#include "dev.h"
24#include "jrand.h"
25#include "lisp.h"
26#include "clisp.h"
27#include "netface.h"
28
29
30demo_manager demo_man;
31int last_demo_mx,last_demo_my,last_demo_mbut;
32extern base_memory_struct *base;   // points to shm_addr
33extern int idle_ticks;
34
35extern void net_receive();
36extern void net_send(int force);
37extern void fade_in(image *im, int steps);
38extern void fade_out(int steps);
39
40void get_event(Event &ev)
41{ wm->get_event(ev);
42  switch (ev.type)
43  {
44    case EV_KEY :
45    {
46      if (demo_man.state==demo_manager::PLAYING)
47        demo_man.set_state(demo_manager::NORMAL);
48      else if (ev.key==JK_ENTER && demo_man.state==demo_manager::RECORDING)
49      {
50        demo_man.set_state(demo_manager::NORMAL);
51    the_game->show_help("Finished recording");
52      }
53    } break;
54  }
55
56  last_demo_mx=ev.mouse_move.x;
57  last_demo_my=ev.mouse_move.y;
58  last_demo_mbut=ev.mouse_button;
59  idle_ticks=0;
60}
61
62int event_waiting()
63{ return wm->event_waiting(); }
64
65
66int demo_manager::start_recording(char *filename)
67{
68  if (!current_level) return 0;
69
70  record_file=open_file(filename,"wb");
71  if (record_file->open_failure()) { delete record_file; return 0; }
72
73  char name[100];
74  strcpy(name,current_level->name());
75
76  the_game->load_level(name);
77  record_file->write((void *)"DEMO,VERSION:2",14);
78  record_file->write_uint8(strlen(name)+1);
79  record_file->write(name,strlen(name)+1);
80
81
82  if (DEFINEDP(symbol_value(l_difficulty)))
83  {
84    if (symbol_value(l_difficulty)==l_easy) record_file->write_uint8(0);
85    else if (symbol_value(l_difficulty)==l_medium) record_file->write_uint8(1);
86    else if (symbol_value(l_difficulty)==l_hard) record_file->write_uint8(2);
87    else record_file->write_uint8(3);
88  } else record_file->write_uint8(3);
89
90
91  state=RECORDING;
92
93  reset_game();
94
95  return 1;
96}
97
98void demo_manager::do_inputs()
99{
100  switch (state)
101  {
102    case RECORDING :
103    {
104      base->packet.packet_reset();       // reset input buffer
105      view *p=player_list;               // get current inputs
106      for (; p; p=p->next)
107        if (p->local_player())
108          p->get_input();
109
110      base->packet.write_uint8(SCMD_SYNC);
111      base->packet.write_uint16(make_sync());
112      demo_man.save_packet(base->packet.packet_data(),base->packet.packet_size());
113      process_packet_commands(base->packet.packet_data(),base->packet.packet_size());
114
115    } break;
116    case PLAYING :
117    {
118      uint8_t buf[1500];
119      int size;
120      if (get_packet(buf,size))              // get starting inputs
121      {
122        process_packet_commands(buf,size);
123    int32_t mx,my;
124    the_game->game_to_mouse(player_list->pointer_x,player_list->pointer_y,player_list,mx,my);
125    wm->set_mouse_position(small_render ? mx*2 : mx, small_render ? my*2 : my);
126      }
127      else
128      {
129    set_state(NORMAL);
130    return ;
131      }
132    } break;
133    default :
134      break;
135  }
136}
137
138void demo_manager::reset_game()
139{
140  if (dev&EDIT_MODE) toggle_edit_mode();
141  the_game->set_state(RUN_STATE);
142  rand_on=0;
143
144  view *v=player_list;
145  for (; v; v=v->next) { if (v->focus) v->reset_player(); }
146
147  last_demo_mx=last_demo_my=last_demo_mbut=0;
148  current_level->set_tick_counter(0);
149
150}
151
152int demo_manager::start_playing(char *filename)
153{
154  uint8_t sig[15];
155  record_file=open_file(filename,"rb");
156  if (record_file->open_failure()) { delete record_file; return 0; }
157  char name[100],nsize,diff;
158  if (record_file->read(sig,14)!=14        ||
159      memcmp(sig,"DEMO,VERSION:2",14)!=0   ||
160      record_file->read(&nsize,1)!=1       ||
161      record_file->read(name,nsize)!=nsize ||
162      record_file->read(&diff,1)!=1)
163  { delete record_file; return 0; }
164
165  char tname[100],*c;
166  strcpy(tname,name);
167  c=tname;
168  while (*c) { if (*c=='\\') *c='/'; c++; }
169
170  bFILE *probe=open_file(tname,"rb");   // see if the level still exists?
171  if (probe->open_failure()) { delete record_file; delete probe; return 0; }
172  delete probe;
173
174  the_game->load_level(tname);
175  initial_difficulty = l_difficulty;
176
177  switch (diff)
178  {
179    case 0: l_difficulty->SetValue(l_easy); break;
180    case 1: l_difficulty->SetValue(l_medium); break;
181    case 2: l_difficulty->SetValue(l_hard); break;
182    case 3: l_difficulty->SetValue(l_extreme); break;
183  }
184
185  state=PLAYING;
186  reset_game();
187
188
189
190  return 1;
191}
192
193int demo_manager::set_state(demo_state new_state, char *filename)
194{
195  if (new_state==state) return 1;
196
197  switch (state)
198  {
199    case RECORDING :
200    { delete record_file; } break;
201    case PLAYING :
202    {
203/*
204      fade_in(cache.img(cache.reg("art/help.spe","sell6",SPEC_IMAGE,1)),8);
205      Timer now; now.WaitMs(2000);
206      fade_out(8);
207*/
208      delete record_file;
209      l_difficulty = initial_difficulty;
210      the_game->set_state(MENU_STATE);
211      wm->Push(new Event(ID_NULL,NULL));
212
213      view *v=player_list;
214      for (; v; v=v->next)  // reset all the players
215      { if (v->focus) { v->reset_player(); v->focus->set_aistate(0); } }
216      delete current_level;
217      current_level=NULL;
218      the_game->reset_keymap();
219      base->input_state=INPUT_PROCESSING;
220
221
222    } break;
223    default :
224      break;
225  }
226
227  switch (new_state)
228  {
229    case RECORDING :
230    { return start_recording(filename); } break;
231    case PLAYING :
232    { return start_playing(filename); } break;
233    case NORMAL :
234    { state=NORMAL; } break;
235  }
236
237  return 1;
238}
239
240int demo_manager::save_packet(void *packet, int packet_size)   // returns non 0 if actually saved
241{
242  if (state==RECORDING)
243  {
244    uint16_t ps=lstl(packet_size);
245    if (record_file->write(&ps,2)!=2 ||
246    record_file->write(packet,packet_size)!=packet_size)
247    {
248      set_state(NORMAL);
249      return 0;
250    }
251    return 1;
252  } else return 0;
253}
254
255int demo_manager::get_packet(void *packet, int &packet_size)   // returns non 0 if actually loaded
256{
257  if (state==PLAYING)
258  {
259    uint16_t ps;
260    if (record_file->read(&ps,2)!=2)
261    {
262      set_state(NORMAL);
263      return 0;
264    }
265    ps=lstl(ps);
266
267    if (record_file->read(packet,ps)!=ps)
268    {
269      set_state(NORMAL);
270      return 0;
271    }
272
273    packet_size=ps;
274    return 1;
275  }
276  return 0;
277}
278
Note: See TracBrowser for help on using the repository browser.