Changeset - 9da66dccab69
[Not reviewed]
default
0 3 1
Silverwing - 7 years ago 2016-12-25 18:54:57

Alternate combat system partially implemented
4 files changed with 327 insertions and 63 deletions:
0 comments (0 inline, 0 general)
battlefield.lua
Show inline comments
 
_kh.bf_calcDistance = function(x1, y1, x2, y2)
 
    return math.max(math.abs(x2 - x1), math.abs(y2 - y1));
 
_kh.bf_calcWalkDistance = function(s, x1, y1, x2, y2)
 
    local closed = {};
 
    local open = {
 
        {p = {{x1, y1}}, l = 0}
 
    };
 
    
 
    --print("call", x2, y2);
 
    
 
    while #open > 0 do
 
        local item = table.remove (open, 1);
 
        
 
        local node = item.p[#item.p];
 
        local inClosed = false;
 
        for i = 1, #closed do
 
            if (closed[i][1] == node[1] and closed[i][2] == node[2]) then
 
                inClosed = true;
 
                break;
 
            end;
 
        end;
 
        if (not inClosed) then
 
            --print(node[1], x2, node[2], y2);
 
            if (node[1] == x2 and node[2] == y2) then
 
                return item;
 
            end;
 
            table.insert(closed, node);
 
            --print("closed", #closed);
 
            --print("open", #open);
 
            
 
            local pos = 1;
 
            while (#open >= pos and open[pos].l <= item.l) do
 
                pos = pos + 1;
 
            end;
 
            
 
            if s:isPassable(node[1], node[2] - 1) or 
 
                (node[1] == x2 and node[2] - 1 == y2) then
 
                local p = {};
 
                for i = 1, #item.p do
 
                    table.insert(p, item.p[i]);
 
                end;
 
                table.insert(p, {node[1], node[2] - 1});
 
                table.insert(open, pos, {
 
                    p = p,
 
                    l = item.l + 1
 
                });
 
            end;
 
            
 
            if s:isPassable(node[1], node[2] + 1) or 
 
                (node[1] == x2 and node[2] + 1 == y2) then
 
                local p = {};
 
                for i = 1, #item.p do
 
                    table.insert(p, item.p[i]);
 
                end;
 
                table.insert(p, {node[1], node[2] + 1});
 
                table.insert(open, pos, {
 
                    p = p,
 
                    l = item.l + 1
 
                });
 
            end;
 
            
 
            
 
            if s:isPassable(node[1] - 1, node[2]) or 
 
                (node[1] - 1 == x2 and node[2] == y2) then
 
                local p = {};
 
                for i = 1, #item.p do
 
                    table.insert(p, item.p[i]);
 
                end;
 
                table.insert(p, {node[1] - 1, node[2]});
 
                table.insert(open, pos, {
 
                    p = p,
 
                    l = item.l + 1
 
                });
 
            end;
 
            
 
            
 
            if s:isPassable(node[1] + 1, node[2]) or 
 
                (node[1] + 1 == x2 and node[2] == y2) then
 
                local p = {};
 
                for i = 1, #item.p do
 
                    table.insert(p, item.p[i]);
 
                end;
 
                table.insert(p, {node[1] + 1, node[2]});
 
                table.insert(open, pos, {
 
                    p = p,
 
                    l = item.l + 1
 
                });
 
            end;
 
        end;
 
    end;
 
    
 
    return nil;
 
end;
 

	
 
_kh.bf_calcShootDistance = function(x1, y1, x2, y2)
 
    --return math.max(math.abs(x2 - x1), math.abs(y2 - y1));
 
    return math.floor(math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)));
 
end;
 

	
 
_kh.bf_calcDirection = function(x1, y1, x2, y2)
 
@@ -32,34 +125,133 @@ end;
 

	
 
battlefield = function(tab)
 
    local make_turn = tab.make_turn;
 
    
 
    tab.isPassable = function(s, x, y)
 
        if (x < 1 or x > 7 or y < 1 or y > 7 or tab.map[y][x] > 0) then
 
            return false;
 
        end;
 
    
 
        for i = 1, #s.obj do 
 
            if (s.obj[i].obst and s.obj[i].obst > 0) then
 
                if (s.obj[i].x == x and s.obj[i].y == y) then
 
                    return false;
 
                end;
 
            end;
 
        end;
 
        
 
        return true;
 
    end;
 
    
 
    tab.isShootable = function(s, x, y)
 
        if (x < 1 or x > 7 or y < 1 or y > 7 or tab.map[y][x] > 1) then
 
            return false;
 
        end;
 
    
 
        for i = 1, #s.obj do 
 
            if (s.obj[i].obst and s.obj[i].obst > 1) then
 
                if (s.obj[i].x == x and s.obj[i].y == y) then
 
                    return false;
 
                end;
 
            end;
 
        end;
 
        
 
        return true;
 
    end;
 
    
 
    tab.canShoot = function(s, x1, y1, x2, y2)
 
        local dx = math.abs(x1 - x2);
 
        local dy = math.abs(y1 - y2);
 
        local invx = x1 > x2;
 
        local invy = y1 > y2;
 
        local xc = 0;
 
        local yc = 0;
 
        local error = 0;
 
        print(dx, dy);
 
        if (dx > dy) then
 
            --horizontal line
 
            local y = 0;
 
            for x = 0, dx do 
 
                if invx then
 
                    xc = x1 - x;
 
                else
 
                    xc = x1 + x;
 
                end;
 
                if invy then
 
                    yc = y1 - y;
 
                else
 
                    yc = y1 + y;
 
                end;
 
                if ((xc ~= x1 or yc ~= y1) and not s:isShootable(xc, yc) and (xc ~= x2 or yc ~= y2)) then
 
                    return false;
 
                end;
 
                
 
                error = error + dy;
 
                if (2 * error > dx) then
 
                    y = y + 1
 
                    error = error - dx;
 
                end;
 
            end;
 
        else
 
            --vertical line
 
            print("2--2");
 
            local x = 0;
 
            for y = 0, dy do
 
                print(x, y);
 
                if invx then
 
                    xc = x1 - x;
 
                else
 
                    xc = x1 + x;
 
                end;
 
                if invy then
 
                    yc = y1 - y;
 
                else
 
                    yc = y1 + y;
 
                end;
 
                print(xc, yc);
 
                if ((xc ~= x1 or yc ~= y1) and not s:isShootable(xc, yc) and (xc ~= x2 or yc ~= y2)) then
 
                    return false;
 
                end;
 
                
 
                error = error + dx;
 
                if (2 * error > dy) then
 
                    x = x + 1;
 
                    error = error - dy;
 
                end;
 
            end;
 
        end;
 
        
 
        return true;
 
    end;
 
    
 
    tab.check_walk = function(s)
 
        bf_north:enable();
 
        bf_northeast:enable();
 
        --bf_northeast:enable();
 
        bf_east:enable();
 
        bf_southeast:enable();
 
        --bf_southeast:enable();
 
        bf_south:enable();
 
        bf_southwest:enable();
 
        --bf_southwest:enable();
 
        bf_west:enable();
 
        bf_northwest:enable();
 
        --bf_northwest:enable();
 
        
 
        if (s.plY == 1) then
 
        if (not s:isPassable(s.plX, s.plY - 1)) then
 
            bf_north:disable();
 
            bf_northeast:disable();
 
            bf_northwest:disable();
 
        elseif (s.plY == 5) then
 
            --bf_northeast:disable();
 
            --bf_northwest:disable();
 
        end;
 
        if (not s:isPassable(s.plX, s.plY + 1)) then
 
            bf_south:disable();
 
            bf_southeast:disable();
 
            bf_southwest:disable();
 
            --bf_southeast:disable();
 
            --bf_southwest:disable();
 
        end;
 
        
 
        if (s.plX == 1) then
 
        if (not s:isPassable(s.plX - 1, s.plY)) then
 
            bf_west:disable();
 
            bf_southwest:disable();
 
            bf_northwest:disable();
 
        elseif (s.plX == 5) then
 
            --bf_southwest:disable();
 
            --bf_northwest:disable();
 
        end;
 
        if (not s:isPassable(s.plX + 1, s.plY)) then
 
            bf_east:disable();
 
            bf_southeast:disable();
 
            bf_northeast:disable();
 
            --bf_southeast:disable();
 
            --bf_northeast:disable();
 
        end;
 
    end;
 
    
 
@@ -109,7 +301,8 @@ battlefield = function(tab)
 
        walk(s.win);
 
    end;
 
    
 
    tab.getDistance = _kh.bf_calcDistance;
 
    tab.getWalkDistance = _kh.bf_calcWalkDistance;
 
    tab.getShootDistance = _kh.bf_calcShootDistance;
 
    tab.getDirection = _kh.bf_calcDirection;
 
    
 
    if (not tab.obj) then
 
@@ -124,18 +317,28 @@ battlefield = function(tab)
 
                    v = v .. ";" .. s.obj[i].pic .. "@" .. tostring(s.obj[i].x * 32 - 32) .. "," .. tostring(s.obj[i].y * 32 - 32);
 
                end;
 
            end;
 
            
 
            for i = 1, 7 do
 
                for j = 1, 7 do
 
                    if (tab.map[i][j] == 2) then
 
                        v = v.. ";images/battle_wall.png@" .. tostring(j * 32 - 32) .. "," .. tostring(i * 32 - 32);
 
                    elseif (tab.map[i][j] == 1) then
 
                        v = v.. ";images/battle_obstacle.png@" .. tostring(j * 32 - 32) .. "," .. tostring(i * 32 - 32);
 
                    end;
 
                end;
 
            end;
 
            return v;
 
        end;
 
    end;
 
    
 
    table.insert(tab.obj, 'bf_north');
 
    table.insert(tab.obj, 'bf_northeast');
 
    --table.insert(tab.obj, 'bf_northeast');
 
    table.insert(tab.obj, 'bf_east');
 
    table.insert(tab.obj, 'bf_southeast');
 
    --table.insert(tab.obj, 'bf_southeast');
 
    table.insert(tab.obj, 'bf_south');
 
    table.insert(tab.obj, 'bf_southwest');
 
    --table.insert(tab.obj, 'bf_southwest');
 
    table.insert(tab.obj, 'bf_west');
 
    table.insert(tab.obj, 'bf_northwest');
 
    --table.insert(tab.obj, 'bf_northwest');
 
    table.insert(tab.obj, 'bf_wait');
 

	
 
    return room(tab);
 
@@ -151,7 +354,7 @@ bf_north = obj {
 
    end;
 
};
 

	
 
bf_northeast = obj {
 
--[[bf_northeast = obj {
 
    nam = "northeast",
 
    dsc = "{На северо-восток}",
 
    act = function(s)
 
@@ -160,7 +363,7 @@ bf_northeast = obj {
 
        p("Вы идете на северо-восток.");
 
        here():make_turn();
 
    end;
 
};
 
};]]
 

	
 
bf_east = obj {
 
    nam = "east",
 
@@ -172,7 +375,7 @@ bf_east = obj {
 
    end;
 
};
 

	
 
bf_southeast = obj {
 
--[[bf_southeast = obj {
 
    nam = "southeast",
 
    dsc = "{На юго-восток}",
 
    act = function(s)
 
@@ -181,7 +384,7 @@ bf_southeast = obj {
 
        p("Вы идете на юго-восток.");
 
        here():make_turn();
 
    end;
 
};
 
};]]
 

	
 
bf_south = obj {
 
    nam = "south",
 
@@ -193,7 +396,7 @@ bf_south = obj {
 
    end;
 
};
 

	
 
bf_southwest = obj {
 
--[[bf_southwest = obj {
 
    nam = "southwest",
 
    dsc = "{На юго-запад}",
 
    act = function(s)
 
@@ -202,7 +405,7 @@ bf_southwest = obj {
 
        p("Вы идете на юго-запад.");
 
        here():make_turn();
 
    end;
 
};
 
};]]
 

	
 
bf_west = obj {
 
    nam = "west",
 
@@ -214,7 +417,7 @@ bf_west = obj {
 
    end;
 
};
 

	
 
bf_northwest = obj {
 
--[[bf_northwest = obj {
 
    nam = "northwest",
 
    dsc = "{На северо-запад}",
 
    act = function(s)
 
@@ -223,7 +426,7 @@ bf_northwest = obj {
 
        p("Вы идете на северо-запад.");
 
        here():make_turn();
 
    end;
 
};
 
};]]
 

	
 
bf_wait = obj {
 
    nam = "wait",
 
@@ -327,6 +530,9 @@ combatant = function(tab)
 
        tab.make_turn = function(s)
 
        end;
 
    end;
 
    if (not tab.obst) then
 
        tab.obst = 2;
 
    end;
 
    
 
    return obj(tab);
 
end;
 
\ No newline at end of file
images/battle_bcg.png
Show inline comments
 
binary diff not shown
Show images
images/battle_wall.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
lseryanotrr_locations.lua
Show inline comments
 
@@ -561,8 +561,17 @@ lse_prison_fight = battlefield {
 
    hideinv = true;
 
    lose = "game_over_lse_prison_fight";
 
    win = "lse_prison_fight_victory";
 
    plX = 3;
 
    plY = 1;
 
    plX = 1;
 
    plY = 6;
 
    map = {
 
        {2,2,0,0,0,2,2},
 
        {0,0,0,0,0,0,0},
 
        {2,2,0,0,0,2,2},
 
        {0,0,0,0,0,0,0},
 
        {2,2,0,0,0,2,2},
 
        {0,0,0,0,0,0,0},
 
        {2,2,0,0,0,2,2}
 
    };
 
    entered = function(s)
 
        move(player_drake, here());
 
        remove(player_phaetlarr);
 
@@ -588,7 +597,7 @@ lse_cmbt_learr = combatant {
 
    nam = "lse_cmbt_learr";
 
    disp2 = "Леарр";
 
    disp3 = "Леарр";
 
    x = 1;
 
    x = 7;
 
    y = 2;
 
    pic = "images/learr.png";
 
    ally = "Я не буду атаковать союзника.";
 
@@ -662,8 +671,8 @@ lse_cmbt_phaetlarr = combatant {
 
    nam = "lse_cmbt_phaetlarr";
 
    disp2 = "Фаэтларра";
 
    disp3 = "Фаэтларру";
 
    x = 3;
 
    y = 5;
 
    x = 4;
 
    y = 7;
 
    pic = "images/phaetlarr.png";
 
    ally = "Я не буду атаковать союзника.";
 
    nohit = "Я не буду атаковать союзника.";
 
@@ -671,6 +680,9 @@ lse_cmbt_phaetlarr = combatant {
 
    hp = 10;
 
    hasSpear = false;
 
    make_turn = function(s)
 
        if (true) then
 
            return;
 
        end;
 
        local enemies = {  };
 
        for item=1,#here().obj do
 
            local obj = here().obj[item];
 
@@ -751,7 +763,7 @@ lse_cmbt_wright = combatant {
 
    nam = "lse_cmbt_wright";
 
    disp2 = "Джека";
 
    disp3 = "Джеку";
 
    x = 5;
 
    x = 1;
 
    y = 2;
 
    pic = "images/jack.png";
 
    ally = "Я не буду атаковать союзника.";
 
@@ -830,7 +842,7 @@ lse_cmbt_radcliffe = combatant {
 
    nam = "lse_cmbt_radcliffe";
 
    disp2 = "Уолтера";
 
    disp3 = "Уолтеру";
 
    x = 5;
 
    x = 1;
 
    y = 4;
 
    pic = "images/walter.png";
 
    ally = "Я не буду атаковать союзника.";
 
@@ -909,7 +921,7 @@ lse_cmbt_anna = combatant {
 
    nam = "lse_cmbt_anna";
 
    disp2 = "Анну";
 
    disp3 = "Анне";
 
    x = 1;
 
    x = 7;
 
    y = 4;
 
    pic = "images/anna.png";
 
    ally = "Я не буду атаковать союзника.";
 
@@ -1022,33 +1034,79 @@ lse_cmbt_guard = function(nam, index, x,
 
            for item=1,#here().obj do
 
                local obj = here().obj[item];
 
                if (obj.ally and obj.hp > 0) then
 
                    table.insert(enemies, obj);
 
                    local p = here():getWalkDistance(s.x, s.y, obj.x, obj.y);
 
                    if (p) then
 
                        table.insert(enemies, {
 
                            o = obj,
 
                            p = p
 
                        });
 
                    end;
 
                end;
 
            end;
 
            table.sort(enemies, function(a, b)
 
                return (here().getDistance(s.x, s.y, b.x, b.y) > here().getDistance(s.x, s.y, a.x, a.y));
 
                return (a.p.l > b.p.l);
 
            end);
 
            
 
            local enemy = enemies[1];
 
            local dist = 9000;
 
            if (not enemy) then
 
            local path = here():getWalkDistance(s.x, s.y, here().plX, here().plY);
 
            if (not enemy or path and enemy.p.l > path.l ) then
 
                enemy = pl;
 
                dist = here().getDistance(s.x, s.y, here().plX, here().plY);
 
            else
 
                dist = here().getDistance(s.x, s.y, enemy.x, enemy.y);
 
                path = enemy.p;
 
                enemy = enemy.o;
 
            end;
 
            print("fug",path);
 
            if (not enemy or not path) then
 
                pn("Стражник ".. tostring(index).. " ждет. ");
 
                return;
 
            end;
 
            
 
            if (dist > here().getDistance(s.x, s.y, here().plX, here().plY)) then
 
                enemy = pl;
 
            end;
 
            -- AI Order:
 
            -- If has spear and enemy is far   - throw spear
 
            -- If has spear and enemy is close - hit with spear
 
            -- if spear is nearer than any enemy - walk towards spear
 
            -- walk towards nearest enemy
 
            -- If enemy close and enemy has spear - take spear from enemy
 
            -- If enemy close and enemy doesn't have spear - hit with claws
 
            -- If enemy close - hit with claws
 
            
 
            if (s.hasSpear and dist == 1) then
 
            if (s.hasSpear) then
 
                print("zoz", math.abs(s.x - enemy.x) + math.abs(s.y - enemy.y),
 
                here():canShoot(s.x,s.y, enemy.x, enemy.y) );
 
                
 
                if (math.abs(s.x - enemy.x) + math.abs(s.y - enemy.y) <= 2 and here():canShoot(s.x,s.y, enemy.x, enemy.y)) then
 
                    if (math.abs(s.x - enemy.x) == 2 or math.abs(s.y - enemy.y) == 2) then
 
                        --50%
 
                        if (rnd(2) > 1) then
 
                            enemy.hp = enemy.hp - 2;
 
                            pn("Стражник ".. tostring(index).. " бьет " .. enemy.disp2 .. " копьем и попадает. ");
 
                        else
 
                            pn("Стражник ".. tostring(index).. " бьет " .. enemy.disp2 .. " копьем, но промахивается. ");
 
                        end;
 
                    elseif  (math.abs(s.x - enemy.x) == 1 and math.abs(s.y - enemy.y) == 1) then
 
                        --75%
 
                        if (rnd(4) > 1) then
 
                            enemy.hp = enemy.hp - 2;
 
                            pn("Стражник ".. tostring(index).. " бьет " .. enemy.disp2 .. " копьем и попадает. ");
 
                        else
 
                            pn("Стражник ".. tostring(index).. " бьет " .. enemy.disp2 .. " копьем, но промахивается. ");
 
                        end;
 
                    else
 
                        --100%
 
                        enemy.hp = enemy.hp - 2;
 
                        pn("Стражник ".. tostring(index).. " бьет " .. enemy.disp2 .. " копьем и попадает. ");
 
                    end;
 
                    return;
 
                end;
 
            else
 
                if (math.abs(s.x - enemy.x) == 1 and s.y == enemy.y or
 
                    s.x == enemy.x and math.abs(s.y - enemy.y) == 1) then
 
                    enemy.hp = enemy.hp - 1;
 
                    pn("Стражник ".. tostring(index).. " бьет " .. enemy.disp2 .. " и попадает. ");
 
                    return;
 
                end;
 
            end;
 
            print("fug2",path);
 
            s.x = path.p[2][1];
 
            s.y = path.p[2][2];
 
            pn("Стражник ".. tostring(index).. " идет к " .. enemy.disp3 .. ". ");
 
            --[[if (s.hasSpear and dist == 1) then
 
                if (rnd(4) > 1) then
 
                    pn("Стражник ".. tostring(index).. " бьет " .. enemy.disp2 .. " копьем и попадает. ");
 
                    enemy.hp = enemy.hp - 2;
 
@@ -1064,28 +1122,28 @@ lse_cmbt_guard = function(nam, index, x,
 
            else
 
                if (enemy.x > s.x) then
 
                    s.x = s.x + 1;
 
                elseif (enemy.x < s.x) then
 
                elseif (enemy.x  s.x) then
 
                    s.x = s.x - 1;
 
                end;
 
                
 
                if (enemy.y > s.y) then
 
                    s.y = s.y + 1;
 
                elseif (enemy.y < s.y) then
 
                elseif (enemy.y  s.y) then
 
                    s.y = s.y - 1;
 
                end;
 
                
 
                pn("Стражник ".. tostring(index).. " идет к " .. enemy.disp3 .. ". ");
 
            end;
 
            end;]]
 
        end;
 
    };
 
end;
 

	
 
lse_cmbt_guard1 = lse_cmbt_guard("lse_cmbt_guard1", 1, 2, 2, false);
 
lse_cmbt_guard2 = lse_cmbt_guard("lse_cmbt_guard2", 2, 2, 3, true);
 
lse_cmbt_guard3 = lse_cmbt_guard("lse_cmbt_guard3", 3, 2, 4, false);
 
lse_cmbt_guard4 = lse_cmbt_guard("lse_cmbt_guard4", 4, 4, 2, false);
 
lse_cmbt_guard5 = lse_cmbt_guard("lse_cmbt_guard5", 5, 4, 3, true);
 
lse_cmbt_guard6 = lse_cmbt_guard("lse_cmbt_guard6", 6, 4, 4, false);
 
lse_cmbt_guard1 = lse_cmbt_guard("lse_cmbt_guard1", 1, 3, 1, false);
 
lse_cmbt_guard2 = lse_cmbt_guard("lse_cmbt_guard2", 2, 5, 1, false);
 
lse_cmbt_guard3 = lse_cmbt_guard("lse_cmbt_guard3", 3, 3, 3, true);
 
lse_cmbt_guard4 = lse_cmbt_guard("lse_cmbt_guard4", 4, 5, 3, true);
 
lse_cmbt_guard5 = lse_cmbt_guard("lse_cmbt_guard5", 5, 3, 5, false);
 
lse_cmbt_guard6 = lse_cmbt_guard("lse_cmbt_guard6", 6, 5, 5, false);
 

	
 
lse_prison_fight_victory = dlg {
 
    nam = "lse_prison_fight_victory";
0 comments (0 inline, 0 general)