|
Crossfire Client, Trunk
R18666
|
00001 const char * const rcsid_common_player_c = 00002 "$Id: player.c 12149 2009-08-20 02:11:28Z kbulgrien $"; 00003 /* 00004 Crossfire client, a client program for the crossfire program. 00005 00006 Copyright (C) 2001 Mark Wedel & Crossfire Development Team 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program; if not, write to the Free Software 00020 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00021 00022 The author can be reached via e-mail to crossfire-devel@real-time.com 00023 */ 00024 00040 #include <client.h> 00041 #include <external.h> 00042 #include <script.h> 00043 00044 /* This translates the numeric direction id's into the actual direction 00045 * commands. This lets us send the actual command (ie, 'north'), which 00046 * makes handling on the server side easier. 00047 */ 00048 00049 const char *const directions[9] = {"stay", "north", "northeast", "east", "southeast", 00050 "south","southwest", "west", "northwest"}; 00051 00052 00053 /* 00054 * Initialiazes player item, information is received from server 00055 */ 00056 void new_player (long tag, char *name, long weight, long face) 00057 { 00058 Spell *spell, *spnext; 00059 00060 cpl.ob->tag = tag; 00061 cpl.ob->nrof = 1; 00062 copy_name (cpl.ob->d_name, name); 00063 cpl.ob->weight = (float) weight / 1000; 00064 cpl.ob->face = face; 00065 00066 if (cpl.spelldata) { 00067 for (spell = cpl.spelldata; spell; spell = spnext) { 00068 spnext = spell->next; 00069 free(spell); 00070 } 00071 cpl.spelldata = NULL; 00072 } 00073 00074 } 00075 00076 void look_at(int x, int y) 00077 { 00078 cs_print_string(csocket.fd, "lookat %d %d", x, y); 00079 } 00080 00081 void client_send_apply (int tag) 00082 { 00083 cs_print_string(csocket.fd, "apply %d", tag); 00084 } 00085 00086 void client_send_examine (int tag) 00087 { 00088 cs_print_string(csocket.fd, "examine %d", tag); 00089 00090 } 00091 00092 /* Requests nrof objects of tag get moved to loc. */ 00093 void client_send_move (int loc, int tag, int nrof) 00094 { 00095 cs_print_string(csocket.fd, "move %d %d %d", loc, tag, nrof); 00096 } 00097 00098 00099 00100 void move_player(int dir) { 00101 /* Should we perhaps use the real repeat count here? */ 00102 send_command(directions[dir], -1, SC_NORMAL); 00103 } 00104 00105 00106 /* Fire & Run code. The server handles repeating of these actions, so 00107 * we only need to send a run or fire command for a particular direction 00108 * once - we use the drun and dfire to keep track if we need to send 00109 * the full command. 00110 */ 00111 static int drun=-1, dfire=-1; 00112 00113 /* Fires in a specified direction. Note that direction 0 is a valid 00114 * case - the fire is centered on the player. 00115 */ 00116 00117 void stop_fire(void) 00118 { 00119 if (cpl.input_state != Playing) return; 00120 dfire |= 0x100; 00121 } 00122 00123 void clear_fire_run(void) 00124 { 00125 if ((dfire!=-1) && (dfire & 0x100)) { 00126 send_command("fire_stop", -1, SC_FIRERUN); 00127 dfire=-1; 00128 } 00129 if ((drun!=-1) && (drun & 0x100)) { 00130 send_command("run_stop", -1, SC_FIRERUN); 00131 drun=-1; 00132 } 00133 } 00134 00135 void clear_fire(void) 00136 { 00137 if (dfire!=-1) { 00138 send_command("fire_stop", -1, SC_FIRERUN); 00139 dfire=-1; 00140 } 00141 } 00142 00143 void clear_run(void) 00144 { 00145 if (drun!=-1) { 00146 send_command("run_stop", -1, SC_FIRERUN); 00147 drun=-1; 00148 } 00149 } 00150 00151 00152 void fire_dir(int dir) { 00153 char buf[MAX_BUF]; 00154 00155 if (cpl.input_state != Playing) return; 00156 if (dir!= dfire) { 00157 snprintf(buf, sizeof(buf), "fire %d", dir); 00158 if (send_command(buf, cpl.count, SC_NORMAL)) { 00159 dfire=dir; 00160 cpl.count=0; 00161 } 00162 } else { 00163 dfire &= 0xff; /* Mark it so that we need a stop_fire */ 00164 } 00165 } 00166 00167 void stop_run(void) 00168 { 00169 send_command("run_stop", -1, SC_FIRERUN); 00170 drun |= 0x100; 00171 } 00172 00173 void run_dir(int dir) { 00174 char buf[MAX_BUF]; 00175 00176 if (dir!=drun) { 00177 snprintf(buf, sizeof(buf), "run %d", dir); 00178 if (send_command(buf, -1, SC_NORMAL)) 00179 drun=dir; 00180 } else { 00181 drun &= 0xff; 00182 } 00183 } 00184 00185 00186 /* This should be used for all 'command' processing. Other functions should 00187 * call this so that proper windowing will be done. 00188 * command is the text command, repeat is a count value, or -1 if none 00189 * is desired and we don't want to reset the current count. 00190 * must_send means we must send this command no matter what (ie, it is 00191 * an administrative type of command like fire_stop, and failure to send 00192 * it will cause definate problems 00193 * return 1 if command was sent, 0 if not sent. 00194 */ 00195 00196 int send_command(const char *command, int repeat, int must_send) { 00197 static char last_command[MAX_BUF]=""; 00198 00199 script_monitor(command,repeat,must_send); 00200 if (cpl.input_state==Reply_One) { 00201 LOG(LOG_ERROR,"common::send_command","Wont send command '%s' - since in reply mode!", 00202 command); 00203 cpl.count=0; 00204 return 0; 00205 } 00206 00207 /* Does the server understand 'ncom'? If so, special code */ 00208 if (csocket.cs_version >= 1021) { 00209 int commdiff=csocket.command_sent - csocket.command_received; 00210 00211 if (commdiff<0) commdiff +=256; 00212 00213 /* if too many unanswered commands, not a must send, and command is 00214 * the same, drop it 00215 */ 00216 if (commdiff>use_config[CONFIG_CWINDOW] && !must_send && !strcmp(command, last_command)) { 00217 if (repeat!=-1) cpl.count=0; 00218 return 0; 00219 #if 0 /* Obnoxious warning message we don't need */ 00220 fprintf(stderr,"Wont send command %s - window oversized %d %d\n", 00221 command, csocket.command_sent, csocket.command_received); 00222 #endif 00223 } 00224 else { 00225 SockList sl; 00226 uint8 buf[MAX_BUF]; 00227 00228 /* Don't want to copy in administrative commands */ 00229 if (!must_send) strcpy(last_command, command); 00230 csocket.command_sent++; 00231 csocket.command_sent &= 0xff; /* max out at 255 */ 00232 00233 SockList_Init(&sl, buf); 00234 SockList_AddString(&sl, "ncom "); 00235 SockList_AddShort(&sl, csocket.command_sent); 00236 SockList_AddInt(&sl, repeat); 00237 SockList_AddString(&sl, command); 00238 SockList_Send(&sl, csocket.fd); 00239 } 00240 } else { 00241 cs_print_string(csocket.fd, "command %d %s", repeat,command); 00242 } 00243 if (repeat!=-1) cpl.count=0; 00244 return 1; 00245 } 00246 00247 void CompleteCmd(unsigned char *data, int len) 00248 { 00249 if (len !=6) { 00250 LOG(LOG_ERROR,"common::CompleteCmd","Invalid length %d - ignoring", len); 00251 return; 00252 } 00253 csocket.command_received = GetShort_String(data); 00254 csocket.command_time = GetInt_String(data+2); 00255 script_sync(csocket.command_sent - csocket.command_received); 00256 } 00257 00258 00259 00260 /* This does special processing on the 'take' command. If the 00261 * player has a container open, we want to specifiy what object 00262 * to move from that since we've sorted it. command is 00263 * the command as tped, cpnext is any optional params. 00264 */ 00265 void command_take (const char *command, const char *cpnext) 00266 { 00267 /* If the player has specified optional data, or the player 00268 * does not have a container open, just issue the command 00269 * as normal 00270 */ 00271 if (cpnext || cpl.container == NULL) 00272 send_command(command, cpl.count, 0); 00273 else { 00274 if (cpl.container->inv == NULL) 00275 draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, 00276 "There is nothing in the container to move"); 00277 else 00278 cs_print_string(csocket.fd,"move %d %d %d", cpl.ob->tag, 00279 cpl.container->inv->tag, cpl.count); 00280 } 00281 }
1.7.6.1