1-- GunFu Deadlands 2-- Copyright 2009-2011 Christiaan Janssen, September 2009-October 2011 3-- 4-- This file is part of GunFu Deadlands. 5-- 6-- GunFu Deadlands is free software: you can redistribute it and/or modify 7-- it under the terms of the GNU General Public License as published by 8-- the Free Software Foundation, either version 3 of the License, or 9-- (at your option) any later version. 10-- 11-- GunFu Deadlands is distributed in the hope that it will be useful, 12-- but WITHOUT ANY WARRANTY; without even the implied warranty of 13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14-- GNU General Public License for more details. 15-- 16-- You should have received a copy of the GNU General Public License 17-- along with GunFu Deadlands. If not, see <http://www.gnu.org/licenses/>. 18 19Editor = {} 20 21function Editor.load() 22 Editor.enabled = false 23 24 Editor.versionstring="GunFuDeadlandsV1.00" 25 26 Editor.defaultmode = 4 27 28 Editor.former_mode = Editor.mode 29 Editor.current_element_index = 2 30 Editor.num_elements = table.getn(Entities.entitystrings) 31 Editor.current_element = Entities.new_element( Editor.current_element_index ) 32 Editor.currentfilename="" 33 Editor.deletefilename = "" 34 Editor.slots={} 35 Editor.listingfilename="listing.gfd" 36 Editor.listingtable={} 37 Editor.listingoffset = 0 38 Editor.listinglength = 10 39 Editor.listingbox={20,60} 40 Editor.fileerror_timer = 0 41 Editor.resetting=false 42 Editor.showprogress = false 43end 44 45function Editor.init() 46 Editor.enabled = true 47 Editor.mode = Editor.defaultmode 48 Editor.dragging = false 49 Editor.dragging_from = {0,0} 50 Editor.shiftpressed = false 51 Editor.mouseposdiff = {0,0} 52 53 -- clear level 54 Level.init() 55 56 Player.pos = {320,240} 57 Player.starting_pos = { 320, 240 } 58 Level.reset_player() 59 60 Editor.firststart = false 61 Editor.wiping = false 62 Editor.resetting=false 63 Editor.showprogress = false 64 65 Editor.loadslotfile( 11 ) 66 Editor.fileerror_timer = 0 67 68 Editor.reset_undo() 69end 70 71function Editor.draw() 72 73 if Editor.mode == 6 then 74 Editor.showprogress = true 75 else 76 Editor.showprogress = false 77 end 78 79 if Editor.mode == 1 -- help 80 then 81 local line1="f1 - This screen\n" 82 local line2="f2 - Save current level into a file (delete with double-rightclick)\n" 83 local line3="f3 - Load level file into editor\n" 84 local line4="f4 - Move: Drag buildings and enemies around with the mouse.\n Erase elements with right click.\n" 85 local line5="f5 - Add: mousewheel or cursor up/down to select element, leftclick \n for inserting new element, drag mouse for fences\n" 86 local line6="f6 - Test: Play current level\n" 87 local line7="f7 - Restart level (resets player and enemies)\n" 88 local line8="f8 - Change level options\n" 89 local line9="f10 - Wipe: erase level completely\n" 90 local line10="0..9 / shift+0..9 - quickload / quicksave\n" 91 local line11="Z / shift+Z - undo/redo\n" 92 local line12="ESC - Exit editor and return to main menu\n" 93 love.graphics.setColor(Colors.dark_black) 94 Graphics.drawtext(line1..line2..line3..line4..line5..line6..line7..line8..line9..line10..line11..line12, 30, 30) 95 96 love.graphics.draw(Graphics.images.f1help, 300, 5) 97 return 98 end 99 100 101 102 if Editor.mode==5 then 103 Graphics.draw() 104 105 if Editor.current_element_index >= Entities.entitylist.barrier_horiz 106 and Editor.current_element_index <= Entities.entitylist.fence_vert and 107 Editor.dragging then 108 Graphics.draw_building( Entities.new_element( Editor.current_element_index, Editor.itemcenter, Editor.itemlength ) ) 109 else 110 Editor.drawelement({love.mouse.getX(), love.mouse.getY()}) 111 end 112 113 love.graphics.draw(Graphics.images.f5add, 300, 5) 114 end 115 116 if Editor.mode==4 then 117 Graphics.draw() 118 love.graphics.draw(Graphics.images.f4move, 300, 5) 119 end 120 121 -- load & save: show files 122 if Editor.mode==2 or Editor.mode==3 then 123 Editor.showFileListing() 124 end 125 126 if Editor.mode==2 then 127 love.graphics.draw(Graphics.images.f2save, 300, 5) 128 end 129 130 if Editor.mode==3 then 131 love.graphics.draw(Graphics.images.f3load, 300, 5) 132 end 133 134 if Editor.mode==4 and Editor.dragging then 135 Editor.drawelement({love.mouse.getX()+Editor.mouseposdiff[1], love.mouse.getY()+Editor.mouseposdiff[2]}) 136 137 end 138 139 if Editor.mode==6 then 140 -- test 141 Graphics.draw() 142 love.graphics.draw(Graphics.images.f6test, 300, 5) 143 end 144 145 if Editor.mode==7 then 146 -- options 147 local ecs="No" 148 if not Level.enemiescanshoot then ecs="Yes" end 149 local ninja="No" 150 if Level.ninjamode then ninja="Yes" end 151 local turns="No" 152 if Level.autoturns then turns="Yes" end 153 local onebullet="No" 154 if Level.onebullet then onebullet="Yes" end 155 love.graphics.setColor(Colors.dark_black) 156 Graphics.drawtext("Click to change:",40,50) 157 Graphics.drawtext("Enemies with no bullets ...... "..ecs, 40,100) 158 Graphics.drawtext("<Thieves in the shadows> mode .... "..ninja, 40,150) 159 Graphics.drawtext("Instantaneous turns .... "..turns, 40, 200) 160 Graphics.drawtext("One bullet per enemy .... "..onebullet, 40, 250) 161 162 love.graphics.draw(Graphics.images.f8opts, 300, 5) 163 end 164 165 if Editor.resetting then 166 love.graphics.draw(Graphics.images.f7reset, 300, 5) 167 end 168 169 if Editor.wiping then 170 love.graphics.draw(Graphics.images.f10wipe, 300, 5) 171 end 172 173end 174 175function Editor.drawelement(position) 176 if Editor.current_element.isbuilding then 177 Editor.current_element.pos = {position[1], position[2]} 178 Graphics.draw_building( Editor.current_element ) 179 else 180 Graphics.drawCentered( Editor.current_element.sprite , love.mouse.getX(), love.mouse.getY() ) 181 end 182end 183 184 185function Editor.showFileListing() 186 187 local x, y = Editor.listingbox[1],Editor.listingbox[2] 188 love.graphics.setColor(Colors.dark_black) 189 local firstline = "File <"..Editor.currentfilename.."> " 190 191 Graphics.drawtext(love.filesystem.getSaveDirectory( ), x, y-30 ) 192 if Editor.fileerror_timer > 0 then 193 if Editor.mode == 2 then 194 firstline = "Error trying to save file" 195 end 196 if Editor.mode == 3 then 197 firstline = "Error loading file" 198 end 199 end 200 201 Graphics.drawtext(firstline,x,y) 202 203 if Editor.listingoffset > 0 then 204 Graphics.drawtext("(UP)",x,y+30) 205 end 206 207 local tolimit = Editor.listinglength 208 local tablelen = table.getn(Editor.listingtable) 209 if tolimit > tablelen then 210 tolimit = tablelen 211 end 212 213 for i=1,tolimit do 214 local fname = Editor.listingtable[i+Editor.listingoffset] 215 Graphics.drawtext(fname, x, y+i*30+30 ) 216 end 217 218 if Editor.listinglength+Editor.listingoffset < tablelen then 219 Graphics.drawtext("(DOWN)",x,y+(Editor.listinglength+2)*30) 220 end 221 222 love.graphics.setLine(1,"rough") 223 love.graphics.line(0,y,screensize[1],y) 224 love.graphics.line(0,y+25,screensize[1],y+25) 225 love.graphics.line(0,y+(Editor.listinglength+2)*30+25,screensize[1],y+(Editor.listinglength+2)*30+25) 226 227 local myf = "F2" 228 if Editor.mode==3 then myf="F3" end 229 Graphics.drawtext("Type filename or double click file in the list. Press "..myf.." to scan dir again.",x,y+(Editor.listinglength+3)*30) 230end 231 232function Editor.update(dt) 233 if Editor.fileerror_timer>0 then 234 Editor.fileerror_timer = Editor.fileerror_timer - dt 235 end 236 237 if Editor.mode == 5 and Editor.dragging then 238 Editor.dragging_to = { love.mouse.getX(), love.mouse.getY() } 239 if Editor.current_element_index >= Entities.entitylist.barrier_horiz 240 and Editor.current_element_index <= Entities.entitylist.fence_vert then 241 local dx = math.abs(Editor.dragging_to[1] - Editor.dragging_from[1]) 242 local dy = math.abs(Editor.dragging_to[2] - Editor.dragging_from[2]) 243 244 if dx > dy then 245 if Editor.current_element_index == Entities.entitylist.barrier_horiz or Editor.current_element_index == Entities.entitylist.barrier_vert then 246 Editor.current_element_index = Entities.entitylist.barrier_horiz 247 Editor.itemlength = math.floor(dx/31) + 1 248 Editor.itemcenter = { math.floor((Editor.dragging_from[1] + Editor.dragging_to[1])/2), Editor.dragging_from[2] } 249 else 250 Editor.current_element_index = Entities.entitylist.fence_horiz 251 Editor.itemlength = math.floor(dx/14) + 1 252 Editor.itemcenter = { math.floor((Editor.dragging_from[1] + Editor.dragging_to[1])/2), Editor.dragging_from[2] } 253 end 254 else 255 if Editor.current_element_index == Entities.entitylist.barrier_horiz or Editor.current_element_index == Entities.entitylist.barrier_vert then 256 Editor.current_element_index = Entities.entitylist.barrier_vert 257 Editor.itemlength = math.floor(dy/32) + 1 258 Editor.itemcenter = { Editor.dragging_from[1], math.floor((Editor.dragging_from[2] + Editor.dragging_to[2])/2) } 259 else 260 Editor.current_element_index = Entities.entitylist.fence_vert 261 Editor.itemlength = math.floor(dy/18) + 1 262 Editor.itemcenter = { Editor.dragging_from[1], math.floor((Editor.dragging_from[2] + Editor.dragging_to[2])/2) } 263 end 264 end 265 end 266 267 end 268 269 270 -- mode = 6, normal update 271 -- other modes... nothing to do I think 272 if Editor.mode == 6 then 273 Game.update(dt) 274 end 275 276 if Editor.mode == 2 or Editor.mode == 3 then 277 278 end 279end 280 281 282 283function Editor.keypressed(key) 284 local oldmode = Editor.mode 285 -- mode selection 286 if key == "f1" then 287 -- help 288 Editor.mode = 1 289 end 290 291 if key == "f2" then 292 -- save 293 if Editor.mode == 2 then 294 -- pressed again: refresh 295 Editor.refreshList() 296 Editor.listingtable = Editor.getFileList() 297 end 298 Editor.mode = 2 299 end 300 301 if key == "f3" then 302 -- load 303 if Editor.mode == 3 then 304 -- pressed again: refresh 305 Editor.refreshList() 306 Editor.listingtable = Editor.getFileList() 307 end 308 Editor.mode = 3 309 end 310 311 if key == "f4" then 312 -- move 313 Editor.mode = 4 314 end 315 316 if key == "f5" then 317 -- add 318 Editor.mode = 5 319 end 320 321 if key == "f6" then 322 -- test 323 Editor.mode = 6 324 end 325 326 if key == "f8" then 327 -- options 328 Editor.mode = 7 329 end 330 331 if key == "escape" then 332 Editor.saveslotfile( 11 ) 333 Editor.mode = Editor.defaultmode 334 Game.titlescreen() 335 end 336 337 if key == "f7" then 338 Editor.resetting=true 339 Level.restart() 340 end 341 342 if key == "f10" then 343 Editor.wiping = true 344 Level.init() -- wipeout 345 Level.restart() 346 Editor.firststart = true 347 Editor.reset_undo() 348 end 349 350 if key == "lshift" or key == "rshift" then 351 Editor.shiftpressed = true 352 end 353 354 if Editor.mode == 5 and key == "up" then 355 Editor.current_element_index = (Editor.current_element_index - 2) % Editor.num_elements + 1 356 -- special= skip element 1 (player) 357 if Editor.current_element_index == 1 then Editor.current_element_index = Editor.num_elements end 358 -- special = skip vertical fences 359 if Editor.current_element_index == Entities.entitylist.barrier_vert or 360 Editor.current_element_index == Entities.entitylist.fence_vert then 361 Editor.current_element_index = Editor.current_element_index - 1 362 end 363 Editor.current_element = Entities.new_element( Editor.current_element_index ) 364 end 365 if Editor.mode == 5 and key == "down" then 366 Editor.current_element_index = Editor.current_element_index % Editor.num_elements + 1 367 -- special = skip vertical fences 368 if Editor.current_element_index == Entities.entitylist.barrier_vert or 369 Editor.current_element_index == Entities.entitylist.fence_vert then 370 Editor.current_element_index = Editor.current_element_index + 1 371 end 372 373 if Editor.current_element_index > Editor.num_elements then Editor.current_element_index = 1 end 374 if Editor.current_element_index == 1 then Editor.current_element_index = 2 end 375 Editor.current_element = Entities.new_element( Editor.current_element_index ) 376 end 377 378 if Editor.mode == 4 or Editor.mode == 5 then 379 if key == "z" then 380 if Editor.shiftpressed then 381 Editor.redo() 382 else 383 Editor.undo() 384 end 385 end 386 end 387 388 -- slots 389 if not (Editor.mode == 2 or Editor.mode==3) then 390 local slot=nil 391 if key=="1" then slot = 1 end 392 if key=="2" then slot = 2 end 393 if key=="3" then slot = 3 end 394 if key=="4" then slot = 4 end 395 if key=="5" then slot = 5 end 396 if key=="6" then slot = 6 end 397 if key=="7" then slot = 7 end 398 if key=="8" then slot = 8 end 399 if key=="9" then slot = 9 end 400 if key=="0" then slot = 10 end 401 if slot then 402 if Editor.shiftpressed then 403 Editor.saveslotfile(slot) 404 else 405 Editor.loadslotfile(slot) 406 end 407 end 408 end 409 410 -- type in filename 411 if Editor.mode == 2 or Editor.mode == 3 then 412 local k = Editor.keyboard_input(key) 413 if k=="back" then 414 if string.len(Editor.currentfilename)>0 then 415 Editor.currentfilename = string.sub(Editor.currentfilename,1,-2) 416 end 417 elseif k=="return" then 418 -- confirm 419 if Editor.fileerror_timer <= 0 and string.len(Editor.currentfilename)>0 then 420 if Editor.mode == 3 then 421 Editor.trytoloadcurrent() 422 else 423 Editor.trytosavecurrent() 424 end 425 end 426 elseif k~="" then 427 Editor.currentfilename = Editor.currentfilename..k 428 end 429 end 430 431 if Editor.mode == 6 then 432 Game.keypressed(key) 433 end 434 435 if Editor.mode ~= oldmode then 436 Editor.fileerror_timer = 0 437 438 -- reload current element when switching state 439 if Editor.current_element_index == Entities.entitylist.barrier_vert then 440 Editor.current_element_index = Entities.entitylist.barrier_horiz 441 end 442 if Editor.current_element_index == Entities.entitylist.fence_vert then 443 Editor.current_element_index = Entities.entitylist.fence_horiz 444 end 445 if Editor.current_element_index == Entities.entitylist.player then 446 Editor.current_element_index = Entities.entitylist.blue_bandit 447 end 448 Editor.current_element = Entities.new_element( Editor.current_element_index ) 449 450 451 -- switching to testmode 452 if Editor.mode == 6 then 453 -- make sure that the "enemyless" flag is correct 454 Level.enemylessmode = (table.getn( Level.enemies ) == 0) 455 if Level.end_time<=0 then Level.end_time = 3 end 456 if Editor.firststart then 457 Level.restart() 458 Editor.firststart = false 459 end 460 -- activate 461 Editor.showprogress = true 462 else 463 Editor.showprogress = false 464 end 465 466 if Editor.mode == 2 or Editor.mode == 3 then 467 -- switching to file mode (load & save) 468 Editor.listingtable = Editor.getFileList() 469 Editor.currentfilename = "" 470 Editor.deletefilename = "" 471 Editor.listingoffset = 0 472 end 473 end 474-- building selection 475end 476 477function Editor.keyboard_input(key) 478 retval = "" 479 if key=="a" then retval = "A" end 480 if key=="b" then retval = "B" end 481 if key=="c" then retval = "C" end 482 if key=="d" then retval = "D" end 483 if key=="e" then retval = "E" end 484 if key=="f" then retval = "F" end 485 if key=="g" then retval = "G" end 486 if key=="h" then retval = "H" end 487 if key=="i" then retval = "I" end 488 if key=="j" then retval = "J" end 489 if key=="k" then retval = "K" end 490 if key=="l" then retval = "L" end 491 if key=="m" then retval = "M" end 492 if key=="n" then retval = "N" end 493 if key=="o" then retval = "O" end 494 if key=="p" then retval = "P" end 495 if key=="q" then retval = "Q" end 496 if key=="r" then retval = "R" end 497 if key=="s" then retval = "S" end 498 if key=="t" then retval = "T" end 499 if key=="u" then retval = "U" end 500 if key=="v" then retval = "V" end 501 if key=="w" then retval = "W" end 502 if key=="x" then retval = "X" end 503 if key=="y" then retval = "Y" end 504 if key=="z" then retval = "Z" end 505 if key=="0" then retval = "0" end 506 if key=="1" then retval = "1" end 507 if key=="2" then retval = "2" end 508 if key=="3" then retval = "3" end 509 if key=="4" then retval = "4" end 510 if key=="5" then retval = "5" end 511 if key=="6" then retval = "6" end 512 if key=="7" then retval = "7" end 513 if key=="8" then retval = "8" end 514 if key=="9" then retval = "9" end 515 if key=="minus" then retval = "-" end 516 if key=="backspace" then retval="back" end 517 if key=="return" then retval="return" end 518 if not Editor.shiftpressed then 519 retval = string.lower(retval) 520 end 521 return retval 522end 523 524function Editor.keyreleased(key) 525 if key == "f7" then 526 Editor.resetting=false 527 end 528 529 if key == "f10" then 530 Editor.wiping = false 531 end 532 533 if key == "lshift" or key == "rshift" then 534 Editor.shiftpressed = false 535 end 536 537 if Editor.mode == 6 then 538 Game.keyreleased(key) 539 end 540 541end 542 543function Editor.mousepressed(x, y, button) 544 if Editor.mode == 4 and button == "l" then 545 local dr = Editor.findfor_substract(x,y) 546 local elem = Editor.substract(x,y) 547 if elem then 548 Editor.register_remove(dr[1],dr[2],dr[3],dr[4],dr[5],1) 549 Editor.dragging = true 550 Editor.current_element = elem 551 Editor.current_element_index = elem.id 552 Editor.current_element_original_pos = {Editor.current_element.pos[1],Editor.current_element.pos[2]} 553 Editor.mouseposdiff = { elem.pos[1] - x, elem.pos[2] - y } 554 end 555 end 556 557 if Editor.mode == 4 and button == "r" then 558 local dr = Editor.findfor_substract(x,y) 559 local elem =Editor.substract(x,y) 560 if elem then 561 Editor.register_remove(dr[1],dr[2],dr[3],dr[4],dr[5]) 562 end 563 end 564 565 if Editor.mode == 5 and button == 'wu' then 566 Editor.current_element_index = (Editor.current_element_index - 2) % Editor.num_elements + 1 567 -- special= skip element 1 (player) 568 if Editor.current_element_index == 1 then Editor.current_element_index = Editor.num_elements end 569 -- special = skip vertical fences 570 if Editor.current_element_index == Entities.entitylist.barrier_vert or 571 Editor.current_element_index == Entities.entitylist.fence_vert then 572 Editor.current_element_index = Editor.current_element_index - 1 573 end 574 Editor.current_element = Entities.new_element( Editor.current_element_index ) 575 end 576 if Editor.mode == 5 and button == 'wd' then 577 Editor.current_element_index = Editor.current_element_index % Editor.num_elements + 1 578 -- special = skip vertical fences 579 if Editor.current_element_index == Entities.entitylist.barrier_vert or 580 Editor.current_element_index == Entities.entitylist.fence_vert then 581 Editor.current_element_index = Editor.current_element_index + 1 582 end 583 584 if Editor.current_element_index > Editor.num_elements then Editor.current_element_index = 1 end 585 if Editor.current_element_index == 1 then Editor.current_element_index = 2 end 586 Editor.current_element = Entities.new_element( Editor.current_element_index ) 587 end 588 589 if Editor.mode == 5 and button == "l" then 590 -- special cases: barrier and fence 591 if Editor.current_element_index >= Entities.entitylist.barrier_horiz 592 and Editor.current_element_index <= Entities.entitylist.fence_vert then 593 Editor.dragging = true 594 Editor.dragging_from = {x,y} 595 else 596 Editor.add_element({x,y}) 597 end 598 599 end 600 601 if Editor.mode==2 or Editor.mode==3 then 602 if button == "l" then 603 if y>Editor.listingbox[2] and y<Editor.listingbox[2]+(Editor.listinglength+2)*30+25 then 604 local index = math.floor((y-Editor.listingbox[2])/30) 605 606 if index>0 then Editor.fileerror_timer = 0 end 607 -- up 608 if index==1 and Editor.listingoffset>0 then 609 Editor.listingoffset = Editor.listingoffset-1 610 end 611 612 -- down 613 if index==(Editor.listinglength+2) and Editor.listingoffset+Editor.listinglength < table.getn(Editor.listingtable) then 614 Editor.listingoffset = Editor.listingoffset+1 615 end 616 617 -- select file 618 if index>=2 and index<=Editor.listinglength+1 then 619 local newindex = index - 1 + Editor.listingoffset 620 if newindex<=table.getn(Editor.listingtable) then 621 local candidatefilename = Editor.listingtable[newindex] 622 -- double click 623 if Editor.currentfilename==candidatefilename then 624 -- load level 625 if Editor.mode == 3 then 626 Editor.trytoloadcurrent() 627 end 628 if Editor.mode == 2 then 629 Editor.trytosavecurrent() 630 end 631 else 632 -- single click 633 Editor.currentfilename = candidatefilename 634 end 635 end 636 end 637 638 -- confirm 639 if index==0 and Editor.fileerror_timer <= 0 and string.len(Editor.currentfilename)>0 then 640 if Editor.mode == 3 then 641 Editor.trytoloadcurrent() 642 else 643 Editor.trytosavecurrent() 644 end 645 end 646 end 647 elseif button == "r" then 648 -- esborrar 649 if y>Editor.listingbox[2] and y<Editor.listingbox[2]+(Editor.listinglength+2)*30+25 then 650 local index = math.floor((y-Editor.listingbox[2])/30) 651 652 if index>0 then Editor.fileerror_timer = 0 end 653 654 -- select file 655 if index>=2 and index<=Editor.listinglength+1 then 656 local newindex = index - 1 + Editor.listingoffset 657 if newindex<=table.getn(Editor.listingtable) then 658 local candidatefilename = Editor.listingtable[newindex] 659 -- double click 660 if Editor.deletefilename==candidatefilename then 661 if Editor.mode == 2 then 662 Editor.deletefile(Editor.deletefilename) 663 end 664 else 665 -- single click 666 Editor.deletefilename = candidatefilename 667 end 668 end 669 end 670 671 672 end 673 elseif button == "wu" and Editor.listingoffset>0 then 674 -- scroll up 675 Editor.listingoffset = Editor.listingoffset-1 676 elseif button == l"wd" and Editor.listingoffset+Editor.listinglength < table.getn(Editor.listingtable)then 677 -- scroll down 678 Editor.listingoffset = Editor.listingoffset+1 679 end 680 end 681 682 if Editor.mode==7 then 683 if x>40 and x<300 and y>75 and y<125 then Level.enemiescanshoot = not Level.enemiescanshoot end 684 if x>40 and x<340 and y>125 and y<175 then Level.ninjamode = not Level.ninjamode end 685 if x>40 and x<250 and y>175 and y<225 then Level.autoturns = not Level.autoturns end 686 if x>40 and x<262 and y>225 and y<275 then Level.onebullet = not Level.onebullet end 687 end 688 689 if Editor.mode == 6 then 690 Game.mousepressed(x, y, button) 691 end 692end 693 694function Editor.add_element(point,len) 695 local x,y = point[1],point[2] 696 -- check collisions! 697 local valid = true 698 if Editor.current_element_index < 6 then -- enemy 699 local enemybox = { x-9, y-11, x+9, y+11 } 700 for i,building in ipairs(Level.buildings) do 701 if mymath.check_boxinbuilding( enemybox, building ) then 702 valid = false 703 break 704 end 705 end 706 -- collision with player 707 708 if valid then 709 local plx,ply = Player.starting_pos[1],Player.starting_pos[2] 710 if Editor.current_element_index ~=Entities.entitylist.player and 711 mymath.check_boxes( enemybox, { plx-9, ply-11, plx+9, ply+11 } ) then 712 valid = false 713 end 714 end 715 -- collision of player 716 if valid and Editor.current_element_index == Entities.entitylist.player then 717 local plx,ply = point[1],point[2] 718 for i,enemy in ipairs(Level.enemies) do 719 local cx,cy = enemy.starting_pos[1],enemy.starting_pos[2] 720 local dx,dy = enemy.spritesize[1]/2, enemy.spritesize[2]/2 721 enemybox = { cx-dx,cy-dy,cx+dx,cy+dy } 722 if mymath.check_boxes( enemybox, { plx-9, ply-11, plx+9, ply+11 } ) then 723 valid = false 724 break 725 end 726 end 727 end 728 729 else -- building 730 local building = Entities.new_element( Editor.current_element_index, {x,y}, len ) 731 for i,enemy in ipairs(Level.enemies) do 732 local cx,cy = enemy.starting_pos[1],enemy.starting_pos[2] 733 local dx,dy = enemy.spritesize[1]/2, enemy.spritesize[2]/2 734 local enemybox = { cx-dx,cy-dy,cx+dx,cy+dy } 735 if mymath.check_boxinbuilding( enemybox, building ) then 736 valid = false 737 break 738 end 739 end 740 -- collision with player 741 local plx,ply = Player.starting_pos[1],Player.starting_pos[2] 742 if valid and mymath.check_boxinbuilding( { plx-9, ply-11, plx+9, ply+11 }, building ) then 743 valid = false 744 end 745 end 746 if valid then 747 Entities.add_element( Editor.current_element_index, {x,y}, len ) 748 749 -- get index in table from class 750 local itemindex = 1 751 if Editor.current_element_index == 1 then 752 itemindex = 1 753 elseif Editor.current_element_index >= Entities.entitylist.blue_bandit and 754 Editor.current_element_index <= Entities.entitylist.yellow_bandit then 755 itemindex = table.getn(Level.enemies) 756 else 757 itemindex = table.getn(Level.buildings) 758 end 759 760 if Editor.mode==5 then 761 Editor.register_add(itemindex, Editor.current_element_index, x, y, len) 762 elseif Editor.mode == 4 and Editor.dragging then 763 Editor.register_add(itemindex, Editor.current_element_index, x, y, len, 1) 764 end 765 end 766 return valid 767end 768 769 770function Editor.mousereleased(x, y, button) 771 if Editor.mode == 4 and button == "l" and Editor.dragging then 772 local len = 1 773 if Editor.current_element.len then len = Editor.current_element.len[2] end 774 if not Editor.add_element( {x+Editor.mouseposdiff[1],y+Editor.mouseposdiff[2]}, len ) 775 then Editor.add_element( Editor.current_element_original_pos, len ) end 776 end 777 778 if Editor.mode ==5 and Editor.dragging and Editor.current_element_index >= Entities.entitylist.barrier_horiz 779 and Editor.current_element_index <= Entities.entitylist.fence_vert then 780 Editor.add_element(Editor.itemcenter, Editor.itemlength) 781 end 782 783 Editor.dragging = false 784 if Editor.mode == 6 then 785 Game.mousereleased(x, y, button) 786 end 787end 788 789function Editor.findfor_substract(x,y) 790 791 for i,building in ipairs(Level.buildings) do 792 if mymath.check_pointinbox( {x,y}, 793 {building.pos[1]-building.sprite:getWidth()/2,building.pos[2]-building.sprite:getHeight()/2, 794 building.pos[1]+building.sprite:getWidth()/2,building.pos[2]+building.sprite:getHeight()/2} ) 795 then 796 if building.id >= Entities.entitylist.barrier_horiz and 797 building.id<= Entities.entitylist.fence_vert then 798 return {i,building.id, building.pos[1], building.pos[2], building.len[2]} 799 else 800 return {i,building.id, building.pos[1], building.pos[2], 1} 801 end 802 end 803 end 804 805 -- find if it's a fence 806 for i,building in ipairs(Level.buildings) do 807 if mymath.check_pointinbuilding( {x,y}, building ) 808 then 809 if building.id >= Entities.entitylist.barrier_horiz and 810 building.id<= Entities.entitylist.fence_vert then 811 return {i,building.id, building.pos[1], building.pos[2], building.len[2]} 812 else 813 return {i,building.id, building.pos[1], building.pos[2], 1} 814 end 815 end 816 end 817 818 -- find if it's an enemy 819 for i,enemy in ipairs(Level.enemies) do 820 if mymath.check_pointinbox( {x,y}, 821 {enemy.pos[1]-enemy.spritesize[1]/2,enemy.pos[2]-enemy.spritesize[2]/2, 822 enemy.pos[1]+enemy.spritesize[1]/2,enemy.pos[2]+enemy.spritesize[2]/2} ) 823 then 824 return {i,enemy.id, enemy.starting_pos[1], enemy.starting_pos[2], 1} 825 end 826 end 827 828 829 -- find if it's the player 830 if mymath.check_pointinbox( {x,y}, 831 {Player.pos[1]-Player.spritesize[1]/2,Player.pos[2]-Player.spritesize[2]/2, 832 Player.pos[1]+Player.spritesize[1]/2,Player.pos[2]+Player.spritesize[2]/2} ) 833 then 834 return {i,1, Player.starting_pos[1], Player.starting_pos[2], 1} 835 end 836 837end 838 839function Editor.substract(x,y) 840 -- returns a reference to the first entity (building or enemy or player) that corresponds to (x,y) 841 -- the thing is that in moving mode, when you click on an entity, it floats on top of the list, becoming 842 -- the last. So if you click repeatedly in the same point where several buildings are overlapping, this 843 -- should always bring the last one on top. 844 845 -- find if it's a building (using the whole sprite, not the regular collision) 846 for i,building in ipairs(Level.buildings) do 847 if mymath.check_pointinbox( {x,y}, 848 {building.pos[1]-building.sprite:getWidth()/2,building.pos[2]-building.sprite:getHeight()/2, 849 building.pos[1]+building.sprite:getWidth()/2,building.pos[2]+building.sprite:getHeight()/2} ) 850 then 851 table.remove(Level.buildings,i) 852 return building 853 end 854 end 855 856 -- find if it's a fence 857 for i,building in ipairs(Level.buildings) do 858 if mymath.check_pointinbuilding( {x,y}, building ) 859 then 860 table.remove(Level.buildings,i) 861 return building 862 end 863 end 864 865 -- find if it's an enemy 866 for i,enemy in ipairs(Level.enemies) do 867 if mymath.check_pointinbox( {x,y}, 868 {enemy.pos[1]-enemy.spritesize[1]/2,enemy.pos[2]-enemy.spritesize[2]/2, 869 enemy.pos[1]+enemy.spritesize[1]/2,enemy.pos[2]+enemy.spritesize[2]/2} ) 870 then 871 table.remove(Level.enemies,i) 872 return enemy 873 end 874 end 875 876 877 -- find if it's the player 878 if mymath.check_pointinbox( {x,y}, 879 {Player.pos[1]-Player.spritesize[1]/2,Player.pos[2]-Player.spritesize[2]/2, 880 Player.pos[1]+Player.spritesize[1]/2,Player.pos[2]+Player.spritesize[2]/2} ) 881 then 882 return Player 883 end 884 885end 886 887function Editor.undo() 888 if Editor.undo_point == Editor.undo_begin then 889 return 890 end 891 892 Editor.rewind_undo_pointer() 893 894 local move = (Editor.undo_list[Editor.undo_point][2]==1) 895 896 -- do the oposite 897 if Editor.undo_list[Editor.undo_point][1] == 1 then 898 -- add, so remove 899 local d = Editor.undo_list[Editor.undo_point] 900 Editor.apply_remove( {d[3], d[4], d[5], d[6], d[7]} ) 901 else 902 -- remove, so add 903 local d = Editor.undo_list[Editor.undo_point] 904 Editor.apply_add( {d[3], d[4], d[5], d[6], d[7]} ) 905 906 end 907 908 909 if move then 910 Editor.rewind_undo_pointer() 911 912 if Editor.undo_list[Editor.undo_point][1] == 1 then 913 -- add, so remove 914 local d = Editor.undo_list[Editor.undo_point] 915 Editor.apply_remove( {d[3], d[4], d[5], d[6], d[7]} ) 916 else 917 -- remove, so add 918 local d = Editor.undo_list[Editor.undo_point] 919 Editor.apply_add( {d[3], d[4], d[5], d[6], d[7]} ) 920 end 921 922 end 923 924end 925 926function Editor.redo() 927 928 929 930 if Editor.undo_point == Editor.undo_end then 931 return 932 end 933 934 935 local move = (Editor.undo_list[Editor.undo_point][2]==1) 936 937 -- do the oposite 938 if Editor.undo_list[Editor.undo_point][1] == 1 then 939 -- add 940 local d = Editor.undo_list[Editor.undo_point] 941 Editor.apply_add( {d[3], d[4], d[5], d[6], d[7]} ) 942 else 943 -- remove 944 local d = Editor.undo_list[Editor.undo_point] 945 Editor.apply_remove( {d[3], d[4], d[5], d[6], d[7]} ) 946 end 947 948 Editor.advance_undo_pointer() 949 950 951 if move then 952 953 954 -- do the oposite 955 if Editor.undo_list[Editor.undo_point][1] == 1 then 956 -- add 957 local d = Editor.undo_list[Editor.undo_point] 958 Editor.apply_add( {d[3], d[4], d[5], d[6], d[7]} ) 959 else 960 -- remove 961 local d = Editor.undo_list[Editor.undo_point] 962 Editor.apply_remove( {d[3], d[4], d[5], d[6], d[7]} ) 963 end 964 965 Editor.advance_undo_pointer() 966 967 end 968 969end 970 971function Editor.apply_add( datalist ) 972 local itemindex, classindex, x, y, len = datalist[1],datalist[2],datalist[3], datalist[4], datalist[5] 973 974 if classindex == 1 then 975 Entities.add_element( 1,{x,y},1 ) 976 elseif classindex >= Entities.entitylist.blue_bandit and classindex <= Entities.entitylist.yellow_bandit then 977 table.insert( Level.enemies, itemindex, Entities.new_element( classindex, {x,y} ) ) 978 else 979 table.insert( Level.buildings, itemindex, Entities.new_element( classindex, {x,y} , len ) ) 980 end 981 982end 983 984function Editor.apply_remove( datalist ) 985 local itemindex, classindex, x, y, len = datalist[1],datalist[2],datalist[3], datalist[4], datalist[5] 986 if classindex==1 then 987 -- player .. ignore 988 elseif classindex >= Entities.entitylist.blue_bandit and classindex <= Entities.entitylist.yellow_bandit then 989 table.remove(Level.enemies, itemindex ) 990 else -- building 991 table.remove(Level.buildings, itemindex ) 992 end 993end 994 995-- undo/redo: three types of actions, add, remove, move (que es remove+add) 996function Editor.register_add( itemindex, classindex, x, y, len, move ) 997 if move==nil then move = 0 end 998 999 Editor.undo_list[Editor.undo_point] = { 1000 1, -- add 1001 move, 1002 itemindex, 1003 classindex, 1004 x, 1005 y, 1006 len } 1007 Editor.push_undo_pointer() 1008end 1009 1010function Editor.register_remove( itemindex, classindex, x, y, len, move ) 1011 if move==nil then move = 0 end 1012 1013 Editor.undo_list[Editor.undo_point] = { 1014 2, -- remove 1015 move, -- no move 1016 itemindex, 1017 classindex, 1018 x, 1019 y, 1020 len } 1021 Editor.push_undo_pointer() 1022end 1023 1024function Editor.push_undo_pointer() 1025 Editor.undo_point = Editor.undo_point + 1 1026 if Editor.undo_point > Editor.undo_max then 1027 Editor.undo_point = 1 1028 end 1029 if Editor.undo_begin == Editor.undo_point then 1030 Editor.undo_begin = Editor.undo_begin + 1 1031 if Editor.undo_begin > Editor.undo_max then 1032 Editor.undo_begin = 1 1033 end 1034 end 1035 Editor.undo_end = Editor.undo_point 1036end 1037 1038function Editor.advance_undo_pointer() 1039 if Editor.undo_point == Editor.undo_end then 1040 return 1041 end 1042 1043 Editor.undo_point = Editor.undo_point + 1 1044 if Editor.undo_point == Editor.undo_max then 1045 Editor.undo_point = 1 1046 end 1047end 1048 1049function Editor.rewind_undo_pointer() 1050 if Editor.undo_point == Editor.undo_begin then 1051 return 1052 end 1053 1054 Editor.undo_point = Editor.undo_point - 1 1055 if Editor.undo_point == 0 then 1056 Editor.undo_point = Editor.undo_max 1057 end 1058end 1059 1060function Editor.reset_undo() 1061-- undo 1062 Editor.undo_list = {} 1063 Editor.undo_point = 1 1064 Editor.undo_max = 400 -- 400 undo actions 1065 Editor.undo_begin = 1 1066 Editor.undo_end = 1 1067end 1068