00001
00016
00017
00018 #include "graffiti.h"
00019
00020 #include "globals.h"
00021 #include "lev_data.h"
00022 #include "obj_column_def.h"
00023 #include "obj_things.h"
00024 #include "obj_slabs.h"
00025 #include "obj_column.h"
00026
00032 short level_free_graffiti(struct LEVEL *lvl)
00033 {
00034 int i;
00035 for (i=lvl->graffiti_count-1; i>=0 ; i--)
00036 {
00037 free (lvl->graffiti[i]->text);
00038 free (lvl->graffiti[i]);
00039 }
00040 if (lvl->graffiti_count>0)
00041 free(lvl->graffiti);
00042 return ERR_NONE;
00043 }
00044
00051 int graffiti_idx(struct LEVEL *lvl, int tx, int ty)
00052 {
00053 return graffiti_idx_next(lvl, tx, ty,-1);
00054 }
00055
00066 int graffiti_idx_next(struct LEVEL *lvl, int tx, int ty, int prev_idx)
00067 {
00068 if (prev_idx < -1) return -1;
00069 int i;
00070 struct DK_GRAFFITI *graf;
00071 for (i=prev_idx+1; i < lvl->graffiti_count; i++)
00072 {
00073 graf = lvl->graffiti[i];
00074 if ((tx>=graf->tile.x) && (tx<=graf->fin_tile.x) && (ty>=graf->tile.y) && (ty<=graf->fin_tile.y))
00075 return i;
00076
00077 if ((ty==graf->tile.y) && (tx==graf->tile.x))
00078 return i;
00079 }
00080 return -1;
00081 }
00082
00090 char *get_graffiti_text(struct LEVEL *lvl,unsigned int num)
00091 {
00092 if ((num>=lvl->graffiti_count) || (num<0))
00093 return "";
00094 return lvl->graffiti[num]->text;
00095 }
00096
00104 void graffiti_del(struct LEVEL *lvl,unsigned int num)
00105 {
00106 int i;
00107 if ((lvl==NULL)||(num>=lvl->graffiti_count))
00108 return;
00109 struct DK_GRAFFITI *graf;
00110 graf=lvl->graffiti[num];
00111 if (graf!=NULL)
00112 {
00113 free(graf->text);
00114 free(graf);
00115 }
00116 int graff_max_idx=lvl->graffiti_count-1;
00117 for (i=num; i < graff_max_idx; i++)
00118 {
00119 lvl->graffiti[i]=lvl->graffiti[i+1];
00120 }
00121
00122 lvl->graffiti_count=graff_max_idx;
00123
00124 lvl->graffiti = (struct DK_GRAFFITI **)realloc(lvl->graffiti,
00125 (graff_max_idx)*sizeof(struct DK_GRAFFITI *));
00126 }
00127
00138 struct DK_GRAFFITI *create_graffiti(int tx, int ty, char *text, const struct LEVEL *lvl, int orient)
00139 {
00140 tx%=lvl->tlsize.x;
00141 ty%=lvl->tlsize.y;
00142 if (text==NULL) return NULL;
00143 struct DK_GRAFFITI *graf;
00144
00145 graf = (struct DK_GRAFFITI *)malloc(sizeof(struct DK_GRAFFITI));
00146 if (graf==NULL)
00147 {
00148 message_error("Cannot alloc memory for graffiti item");
00149 return NULL;
00150 }
00151 graf->tile.x=tx;
00152 graf->tile.y=ty;
00153 graf->font=GRAFF_FONT_ADICLSSC;
00154 graf->cube=0x0184;
00155 graf->text = strdup(text);
00156 set_graffiti_orientation(graf,lvl,orient);
00157 return graf;
00158 }
00159
00167 int graffiti_add_obj(struct LEVEL *lvl,struct DK_GRAFFITI *graf)
00168 {
00169 if ((lvl==NULL)||(graf==NULL)) return -1;
00170
00171 int graf_idx=lvl->graffiti_count;
00172 lvl->graffiti = (struct DK_GRAFFITI **)realloc (lvl->graffiti,
00173 (graf_idx+1)*sizeof(struct DK_GRAFFITI *));
00174 if (lvl->graffiti==NULL)
00175 {
00176 message_error("Cannot alloc memory for graffiti array");
00177 return -1;
00178 }
00179 lvl->graffiti[graf_idx]=graf;
00180 lvl->graffiti_count=graf_idx+1;
00181 return graf_idx;
00182 }
00183
00193 short set_graffiti_orientation(struct DK_GRAFFITI *graf,const struct LEVEL *lvl,unsigned short orient)
00194 {
00195 if ((graf==NULL)||(graf->text==NULL)) return false;
00196
00197 int arr_entries_x=lvl->tlsize.x*MAP_SUBNUM_X;
00198 int arr_entries_y=lvl->tlsize.y*MAP_SUBNUM_Y;
00199 unsigned short font=graf->font;
00200 int i;
00201 int l;
00202 l = strlen(graf->text);
00203
00204 int subtl_len=0;
00205 for (i=0; i<l; i++)
00206 {
00207
00208
00209
00210 subtl_len+=get_font_char(font,graf->text[i])[0]+1;
00211 int graf_end_subtl_x,graf_end_subtl_y;
00212 switch (orient)
00213 {
00214 case ORIENT_NS:
00215 case ORIENT_SN:
00216 graf_end_subtl_x=graf->tile.x*MAP_SUBNUM_X;
00217 graf_end_subtl_y=graf->tile.y*MAP_SUBNUM_Y+subtl_len;
00218 break;
00219 case ORIENT_WE:
00220 case ORIENT_EW:
00221 graf_end_subtl_x=graf->tile.x*MAP_SUBNUM_X+subtl_len;
00222 graf_end_subtl_y=graf->tile.y*MAP_SUBNUM_Y;
00223 break;
00224 case ORIENT_TNS:
00225 case ORIENT_TSN:
00226 graf_end_subtl_x=graf->tile.x*MAP_SUBNUM_X;
00227 graf_end_subtl_y=graf->tile.y*MAP_SUBNUM_Y+subtl_len;
00228 break;
00229 case ORIENT_TWE:
00230 case ORIENT_TEW:
00231 graf_end_subtl_x=graf->tile.x*MAP_SUBNUM_X+subtl_len;
00232 graf_end_subtl_y=graf->tile.y*MAP_SUBNUM_Y;
00233 break;
00234 default:
00235 graf_end_subtl_x=graf->tile.x*MAP_SUBNUM_X;
00236 graf_end_subtl_y=graf->tile.y*MAP_SUBNUM_Y;
00237 break;
00238 }
00239
00240
00241 if ((graf_end_subtl_x > arr_entries_x)||(graf_end_subtl_y > arr_entries_y))
00242 {
00243 l=i;
00244 break;
00245 }
00246 }
00247
00248 subtl_len--;
00249
00250 int tiles_len=(subtl_len/MAP_SUBNUM_X) + ((subtl_len%MAP_SUBNUM_X)>0);
00251 if (tiles_len<1) tiles_len=1;
00252
00253 int txt_height=get_graffiti_cube_height(graf->font,graf->text);
00254 int txt_tile_height=(txt_height/MAP_SUBNUM_X)+((txt_height%MAP_SUBNUM_X)>0);
00255
00256 graf->orient=orient;
00257 int graf_h=6-txt_height;
00258 if ((graf_h<0)||(graf_h>7))
00259 graf_h=0;
00260 switch (orient)
00261 {
00262 case ORIENT_NS:
00263 case ORIENT_SN:
00264 graf->fin_tile.x = graf->tile.x;
00265 graf->fin_tile.y = graf->tile.y+tiles_len-1;
00266 graf->height=graf_h;
00267 break;
00268 case ORIENT_WE:
00269 case ORIENT_EW:
00270 graf->fin_tile.x = graf->tile.x+tiles_len-1;
00271 graf->fin_tile.y = graf->tile.y;
00272 graf->height=graf_h;
00273 break;
00274 case ORIENT_TNS:
00275 case ORIENT_TSN:
00276 graf->fin_tile.x = graf->tile.x+txt_tile_height-1;
00277 graf->fin_tile.y = graf->tile.y+tiles_len-1;
00278 if (slab_is_tall(get_tile_slab(lvl,graf->tile.x,graf->tile.y)))
00279 graf->height=4;
00280 else
00281 graf->height=0;
00282 break;
00283 case ORIENT_TWE:
00284 case ORIENT_TEW:
00285 graf->fin_tile.x = graf->tile.x+tiles_len-1;
00286 graf->fin_tile.y = graf->tile.y+txt_tile_height-1;
00287 if (slab_is_tall(get_tile_slab(lvl,graf->tile.x,graf->tile.y)))
00288 graf->height=4;
00289 else
00290 graf->height=0;
00291 break;
00292 default:
00293 graf->fin_tile.x = graf->tile.x+tiles_len-1;
00294 graf->fin_tile.y = graf->tile.y+tiles_len-1;
00295 graf->height=graf_h;
00296 break;
00297 }
00298 return ERR_NONE;
00299 }
00300
00308 int set_graffiti_height(struct DK_GRAFFITI *graf,int height)
00309 {
00310 if (graf==NULL) return 0;
00311 int height_max;
00312 switch (graf->orient)
00313 {
00314 case ORIENT_NS:
00315 case ORIENT_SN:
00316 case ORIENT_WE:
00317 case ORIENT_EW:
00318 height_max=7-get_graffiti_cube_height(graf->font,graf->text);
00319 break;
00320 case ORIENT_TNS:
00321 case ORIENT_TSN:
00322 case ORIENT_TWE:
00323 case ORIENT_TEW:
00324 default:
00325 height_max=7;
00326 break;
00327 }
00328 if (height<0) height=0;
00329 if (height>height_max) height=height_max;
00330 graf->height=height;
00331 return height;
00332 }
00333
00346 int graffiti_add(struct LEVEL *lvl,int tx, int ty,int height, char *text,int font,
00347 unsigned short orient,unsigned short cube)
00348 {
00349 if ((lvl==NULL)||(text==NULL)||(strlen(text)<1)) return -1;
00350 struct DK_GRAFFITI *graf=create_graffiti(tx,ty,text,lvl,orient);
00351 if (graf==NULL) return false;
00352 graf->font=font;
00353 graf->height=height;
00354 graf->cube=cube;
00355 int graf_idx=graffiti_add_obj(lvl,graf);
00356 if (graf_idx<0)
00357 {
00358 free(graf->text);
00359 free(graf);
00360 }
00361 return graf_idx;
00362 }
00363
00369 void graffiti_update_columns(struct LEVEL *lvl,int graf_idx)
00370 {
00371 if (graf_idx<0) return;
00372 struct DK_GRAFFITI *graf;
00373 graf=get_graffiti(lvl, graf_idx);
00374 if (graf==NULL) return;
00375 update_datclm_for_square(lvl,graf->tile.x,graf->fin_tile.x,graf->tile.y,graf->fin_tile.y);
00376 }
00377
00384 void graffiti_clear_from_columns(struct LEVEL *lvl,int graf_idx)
00385 {
00386 if (graf_idx<0) return;
00387 struct DK_GRAFFITI *graf;
00388 graf=get_graffiti(lvl, graf_idx);
00389 if (graf==NULL) return;
00390 int tx,fin_tx,ty,fin_ty;
00391
00392 tx=graf->tile.x;graf->tile.x=lvl->tlsize.x;
00393 fin_tx=graf->fin_tile.x;graf->fin_tile.x=lvl->tlsize.x;
00394 ty=graf->tile.y;graf->tile.y=lvl->tlsize.y;
00395 fin_ty=graf->fin_tile.y;graf->fin_tile.y=lvl->tlsize.y;
00396
00397 update_datclm_for_square(lvl,tx,fin_tx,ty,fin_ty);
00398
00399 graf->tile.x=tx;
00400 graf->fin_tile.x=fin_tx;
00401 graf->tile.y=ty;
00402 graf->fin_tile.y=fin_ty;
00403 }
00404
00410 unsigned int get_graffiti_count(struct LEVEL *lvl)
00411 {
00412 if (lvl==NULL) return 0;
00413 return lvl->graffiti_count;
00414 }
00415
00422 struct DK_GRAFFITI *get_graffiti(struct LEVEL *lvl, int graf_idx)
00423 {
00424 if ((graf_idx<0)||(graf_idx>=lvl->graffiti_count)) return NULL;
00425 return lvl->graffiti[graf_idx];
00426 }
00427
00434 int compute_graffiti_subtl_length(unsigned short font,char *text)
00435 {
00436 if (text==NULL) return 0;
00437 int l = strlen(text);
00438 if (l<1) return 0;
00439 switch (font)
00440 {
00441 case GRAFF_FONT_ADICLSSC:
00442 case GRAFF_FONT_ADISIZE8:
00443 break;
00444 case GRAFF_FONT_NONE:
00445 default:
00446 return 0;
00447 }
00448
00449 int i;
00450 int subtl_len=0;
00451 for (i=0; i < l; i++)
00452 {
00453
00454
00455
00456 subtl_len+=get_font_char(font,text[i])[0]+1;
00457 }
00458
00459 subtl_len--;
00460 return subtl_len;
00461 }
00462
00469 int get_graffiti_cube_height(unsigned short font,char *text)
00470 {
00471
00472
00473 switch (font)
00474 {
00475 case GRAFF_FONT_ADICLSSC:
00476 return font_adiclssc_height;
00477 case GRAFF_FONT_ADISIZE8:
00478 return font_adisize8_height;
00479 default:
00480 return 0;
00481 }
00482 }
00483
00490 const unsigned char *get_font_char(unsigned short font,char chr)
00491 {
00492 switch (font)
00493 {
00494 case GRAFF_FONT_ADICLSSC:
00495 return font_adiclssc_chars[(unsigned char)chr];
00496 case GRAFF_FONT_ADISIZE8:
00497 return font_adisize8_chars[(unsigned char)chr];
00498 default:
00499 return font_any_chnull;
00500 }
00501 }
00502
00511 int place_graffiti_on_slab(struct COLUMN_REC *clm_recs[9],struct LEVEL *lvl, int tx, int ty)
00512 {
00513 static const int dy[4][3]={{0,1,2}, {2,2,2}, {2,1,0}, {0,0,0}};
00514 static const int dx[4][3]={{0,0,0}, {0,1,2}, {2,2,2}, {2,1,0}};
00515 int mod_clms=0;
00516 int graf_idx=-1;
00517 while ((graf_idx=graffiti_idx_next(lvl,tx,ty,graf_idx))>=0)
00518 {
00519 struct DK_GRAFFITI *graf;
00520 graf=get_graffiti(lvl,graf_idx);
00521 if (graf==NULL) continue;
00522
00523 int i;
00524 int base_sx=graf->tile.x*MAP_SUBNUM_X;
00525 int base_sy=graf->tile.y*MAP_SUBNUM_Y;
00526
00527 int subtl_len=compute_graffiti_subtl_length(graf->font,graf->text);
00528
00529 int graf_subtl_start;
00530
00531
00532 short orient_top=false;
00533 switch (graf->orient)
00534 {
00535 case ORIENT_TNS: orient_top=true;
00536 case ORIENT_NS: graf_subtl_start=ty*MAP_SUBNUM_Y-base_sy; break;
00537 case ORIENT_TSN: orient_top=true;
00538 case ORIENT_SN: graf_subtl_start=(base_sy+subtl_len-1)-ty*MAP_SUBNUM_Y; break;
00539 case ORIENT_TWE: orient_top=true;
00540 case ORIENT_WE: graf_subtl_start=tx*MAP_SUBNUM_X-base_sx; break;
00541 case ORIENT_TEW: orient_top=true;
00542 case ORIENT_EW: graf_subtl_start=(base_sx+subtl_len-1)-tx*MAP_SUBNUM_X; break;
00543 default: graf_subtl_start=0; break;
00544 }
00545 if (orient_top)
00546 {
00547 int subtl_h=get_graffiti_cube_height(graf->font,graf->text);
00548 int graf_subtl_h_st;
00549 switch (graf->orient)
00550 {
00551 case ORIENT_TNS: graf_subtl_h_st=tx*MAP_SUBNUM_X-base_sx; break;
00552 case ORIENT_TSN: graf_subtl_h_st=(base_sx+subtl_h-1)-(tx+1)*MAP_SUBNUM_X; break;
00553 case ORIENT_TWE: graf_subtl_h_st=(base_sy+subtl_h-1)-(ty+1)*MAP_SUBNUM_Y; break;
00554 case ORIENT_TEW: graf_subtl_h_st=ty*MAP_SUBNUM_Y-base_sy; break;
00555 default: graf_subtl_h_st=0; break;
00556 }
00557 for (i=0; i<MAP_SUBNUM_X; i++)
00558 {
00559 int k;
00560 int graf_subtl=graf_subtl_start+i;
00561 for (k=0; k<MAP_SUBNUM_Y; k++)
00562 {
00563 int subtl;
00564 switch (graf->orient)
00565 {
00566 case ORIENT_TNS: subtl=i*MAP_SUBNUM_X + k; break;
00567 case ORIENT_TSN: subtl=(2-i)*MAP_SUBNUM_X + (2-k); break;
00568 case ORIENT_TWE: subtl=(2-k)*MAP_SUBNUM_X + i; break;
00569 case ORIENT_TEW: subtl=k*MAP_SUBNUM_X + (2-i); break;
00570 default: subtl=0; break;
00571 }
00572 int graf_subtl_h=graf_subtl_h_st+k;
00573 short modified=place_graffiti_on_clm_top(clm_recs[subtl],graf->font,
00574 graf->height,graf->text,graf_subtl,graf_subtl_h,graf->cube);
00575 if (modified) mod_clms++;
00576 }
00577 }
00578 } else
00579 {
00580 unsigned short or=((graf->orient%4));
00581 for (i=0; i<MAP_SUBNUM_X; i++)
00582 {
00583 int subtl=dy[or][i]*MAP_SUBNUM_X + dx[or][i];
00584 int graf_subtl=graf_subtl_start+i;
00585 short modified=place_graffiti_on_column(clm_recs[subtl],graf->font,
00586 graf->height,graf->text,graf_subtl,graf->cube);
00587 if (modified) mod_clms++;
00588 }
00589 }
00590 }
00591 return mod_clms;
00592 }
00593
00605 short place_graffiti_on_clm_top(struct COLUMN_REC *clm_rec,unsigned short font,
00606 unsigned short height,char *text,int graf_subtl,int graf_subtl_h,
00607 unsigned short cube)
00608 {
00609 if ((clm_rec==NULL)||(text==NULL)||(strlen(text)<1)) return false;
00610 int i;
00611 int l = strlen(text);
00612 int text_pos=0;
00613 int clm_pos=0;
00614 i=0;
00615 for (text_pos=0; text_pos<l; text_pos++)
00616 {
00617
00618
00619 int chr_clms_count=get_font_char(font,text[text_pos])[0]+1;
00620 if ((i<=graf_subtl)&&(i+chr_clms_count>graf_subtl))
00621 {
00622
00623
00624 clm_pos=graf_subtl-i+1;
00625 break;
00626 }
00627 i+=chr_clms_count;
00628 }
00629
00630 if (text_pos>=l) return false;
00631 const unsigned char *char_data=get_font_char(font,text[text_pos]);
00632
00633 if ((clm_pos<=0)||(clm_pos>char_data[0])) return false;
00634 unsigned char clm_mask=char_data[clm_pos];
00635 if ((clm_mask>>graf_subtl_h)&0x01)
00636 {
00637 if (height<8) clm_rec->c[height]=cube;
00638 }
00639 clm_rec->solid=compute_clm_rec_solid(clm_rec);
00640 clm_rec->height=compute_clm_rec_height(clm_rec);
00641 return true;
00642 }
00643
00654 short place_graffiti_on_column(struct COLUMN_REC *clm_rec,unsigned short font,
00655 unsigned short height,char *text,int graf_subtl,unsigned short cube)
00656 {
00657 if ((clm_rec==NULL)||(text==NULL)||(strlen(text)<1)) return false;
00658 int i;
00659 int l = strlen(text);
00660 int text_pos=0;
00661 int clm_pos=0;
00662 i=0;
00663 for (text_pos=0; text_pos<l; text_pos++)
00664 {
00665
00666
00667 int chr_clms_count=get_font_char(font,text[text_pos])[0]+1;
00668 if ((i<=graf_subtl)&&(i+chr_clms_count>graf_subtl))
00669 {
00670
00671
00672 clm_pos=graf_subtl-i+1;
00673 break;
00674 }
00675 i+=chr_clms_count;
00676 }
00677
00678 if (text_pos>=l) return false;
00679 const unsigned char *char_data=get_font_char(font,text[text_pos]);
00680
00681 if ((clm_pos<=0)||(clm_pos>char_data[0])) return false;
00682 unsigned char clm_mask=char_data[clm_pos];
00683 for (i=0;i<8;i++)
00684 {
00685 if ((clm_mask>>i)&0x01)
00686 {
00687 int idx=i+height;
00688 if ((idx>=0)&&(idx<8)) clm_rec->c[idx]=cube;
00689 }
00690 }
00691 clm_rec->solid=compute_clm_rec_solid(clm_rec);
00692 clm_rec->height=compute_clm_rec_height(clm_rec);
00693 return true;
00694 }