#include "mith.h"
#include "ryc_zak.h"
#include <files.h>

#ifndef W_WARHAMMER

#define W_WARHAMMER 4
#define SS_WEP_WARHAMMER W_WARHAMMER

#endif

#define OBR_BRAK 0
#define OBR_BLEKKIE 1
#define OBR_LEKKIE 2
#define OBR_SREDNIE 4
#define OBR_CIEZKIE 8
#define OBR_BCIEZKIE 16
#define OBR_SMIERTELNE 32

#define MINIMALNA_WAGA 5000
#define DOZWOLONE_BRONIE ({W_SWORD,W_AXE,W_WARHAMMER,W_POLEARM})

#define MECZENIE_PRZED      1
#define MECZENIE_PO     1

public void do_boju(object ja, object cel, object bron, object paraliz);
int jakie_obr(int proc);
void wyswietl_opisy(object ja, object cel, int numer_obr);


/* Funkcja wywolywana przez komende 'szarzuj'
 */
int
szarzuj(string str, object ofiara)
{
    float czas;
    object *oblist,p;
    object miecz = TP->query_weapon(W_BOTH);
    object paraliz;
    oblist = parse_this(str,"'na' %l:"+PL_BIE);

    if (!miecz)
	miecz=TP->query_weapon(W_RIGHT);
    if (!miecz)
	miecz=TP->query_weapon(W_LEFT);
	
	if (!miecz)
	    {
	    write("Dobadz broni.\n");
	    return 1;
	    }


    if (sizeof(oblist) > 1)
    {
        notify_fail("Na kogo konkretnie chcesz zaszarzowac?\n");
        return 0;
    }
    if (sizeof(oblist) == 0)
    {
        notify_fail("Na kogo chcesz zaszarzowac?\n");
        return 0;
    }
     // Mor: Mith musi sie tym zajac to jego kocepcja :)
    if (TP->query_prop(OBJ_I_WEIGHT) < MINIMALNA_WAGA) // probnie, potem zwiekszymy.
    {
        notify_fail("Masz zbyt mala mase, aby skutecznie " +
            "zaszarzowac. Sproboj wiecej jesc lub nosic " +
            "ciezsza zbroje.\n");
        return 0;
    }

    if (!miecz)
    {
        notify_fail("Musisz dzierzyc jakas bron, aby moc zaszarzowac.\n");
        return 0;
    }

    if (member_array(miecz->query_wt(), DOZWOLONE_BRONIE) < 0)
    {
    // Mor: to jak z tymi polearmami? Moga byc czy nie? :)
    // (kod pozwala na ich uzywanie)
          notify_fail("Przy pomocy tej broni raczej nie da sie " +
              "przeprowadzic szarzy.\n");
        return 0;
    }

    if (environment(TP)->query_prop(ROOM_M_NO_ATTACK))
    {
        if (stringp(environment(TP)->query_prop(ROOM_M_NO_ATTACK)))
            write(environment(TP)->query_prop(ROOM_M_NO_ATTACK));
        else
            write("W tym miejscu nie mozesz przeprowadzac szarzy.\n");
        return 0;
    }

    if (TP->query_prop(RZ_SPECJAL))
    {
        write("Musisz odczekac troche czasu, zanim bedziesz mogl" +
            TP->koncowka("","a") + " ponownie zaszarzowac.\n");
        return 1;
    }

    if (!TP->query_skill(RZ_SZARZA))
    {
        notify_fail("Musisz poznac przynajmniej podstawy tej techniki walki, "+
            "aby moc z niej skutecznie korzystac.\n");
        return 0;
    }

    if (TP->query_attack() || oblist[0]->query_attack() == TP)
    {
        write("Nie mozesz szarzowac podczas walki.\n");
        return 1;
    }
    if (obiekt_no_attack(TP, oblist[0]))
        return 0;

    if (TP->query_fatigue() < (MECZENIE_PRZED + MECZENIE_PO))
    {
        write("Jestes zbyt zmeczon" + TP->koncowka("y", "a") + ", by moc " +
            "szarzowac.\n");
        return 1;
    }

    if (TP->query_prop(RZ_TEMP) || TP->query_prop(LIVE_O_SPELL_ATTACK)) return notify_fail("Juz przygotowywujesz jeden cios.\n");


// Najwidoczniej spelnia podstawowe warunki... teraz zrobimy przygotowanie
// do ataku.

/* Czas przygotowania: W zaleznosci od skilla:
 *    6 sekund (skill 0) - 3 sekundy (skill 100)
 */

    setuid();
    seteuid(getuid());
    paraliz=clone_object(ENGINE+"paraliz_szarza.c");
    paraliz->move(TP);
    czas = 0.1;
    TP->reveal_me(1);

    TP->catch_msg("Przygotowujesz sie do szarzy, a twe cialo plonie gniewem "
        + "Sigmara, przed ktorym nie ostoi sie zaden sluga Chaosu.\n");
    tell_room(environment(TP),""+QCIMIE(TP,PL_MIA) + " wznosi nad glowe "+
        ""+miecz->short(TP,PL_MIA)+" i rusza na "+QIMIE(oblist[0], PL_BIE)+" "+
        ". W je"+TP->koncowka("go", "j")+" oczach plonie ogien "+
        "gniewu Sigmara, przed ktorym nie ostoi sie zaden sluga Chaosu.\n",
        ({TP, ofiara}));
    ofiara->catch_msg("TEN MISZCZUNIO NA CIEBIE SZARZUJE.\n");

    TP->add_fatigue(-MECZENIE_PRZED);

    TP->add_prop(RZ_TEMP, set_alarm(czas, 0.0, "do_boju", TP, oblist[0], miecz, paraliz));

    return 1;
}

public void
do_boju(object ja, object cel, object bron, object paraliz)
{
   object miecz = (TP->query_weapon(W_RIGHT) ||
                TP->query_weapon(W_BOTH) ||
                TP->query_weapon(W_LEFT));
    // Lub nie sprawdza drugiego wyrazenia, jesli pierwsze jest prawdziwe.
    // Mozna zrobic tez (miecz=TP->... || miecz=TP->query...)

    object room = environment(ja);
    string konc1=TP->koncowka("", "a");
    string konc2=cel->koncowka("", "a");
    int numer_alarmu;
    int proc_obr;
    int cios, trafienie;
    int numer_obr; // jaki opis, lekki, sredni, ciezki czy zabity
    string obr;
    string konc = miecz->koncowka("tym","ta");
    mixed sila;
    paraliz->remove_object();
    ja->remove_prop(RZ_TEMP);

    if (miecz != bron)
    {
        write("Nie mozesz zmieniac broni podczas przygotowan do szarzy.\n");
        return;
    }

    if (!present(cel,room))
    {
        write("Twego celu juz tutaj nie ma.\n");
        allbb("wyglada, jakby sie rozmyslil"+konc1+" i juz nie mial"+konc1+
            " zamiaru szarzowac.");
        return;
    }

//A: Sprawdzenie na walke tutaj jest swinskie dla rycerzy, bo jak ktos
//   zobaczy, ze rycerz na niego szarzuje, to go zaatakuje w czasie
//   przygotowania, a rycerz nie bedzie mogl szrrzy do konczyc. To trzeba
//   bedzie jeszcze omowic.
//M: Swinskie... Ale po to to jest...
//A: W sumie, czemuby nie. :-E
    if (ja->query_attack())
    {
        write("Nie mozesz szarzowac podczas walki.\n");
        return;
    }

    ja->catch_msg("Szarzujesz na " + cel->query_imie(ja, PL_BIE) + ".\n");
    cel->catch_msg(ja->query_Imie(cel, PL_MIA) + " szarzuje na ciebie " +
        "z wyciagnie" + konc + " w gore " + miecz->short(cel, PL_NAR) +
        ".\n");
    tell_room(room, QCIMIE(ja, PL_MIA) + " szarzuje z wyciagnie" + konc +
        " w gore " + QSHORT(miecz, PL_NAR) + " na " + QIMIE(cel, PL_BIE) +
        ".\n", ({ ja, cel }));

    ja->add_prop(RZ_SPECJAL, set_alarm(1.0, 0.0, "usun_specjala",ja));

    ja->add_fatigue(-MECZENIE_PO);

    ja->attack_object(cel);
    cel->attack_object(ja);

    if (!(trafienie=trafil_szarza(ja, cel, miecz->query_wt())))
    {
        cel->catch_msg("Zrecznie unikasz zbyt wolno zadanego ciosu.\n");
        ja->catch_msg(QCIMIE(cel, PL_MIA) + " zrecznie unika zbyt wolno " +
            "zadanego przez ciebie ciosu.\n");
        tell_room(room, QCIMIE(cel, PL_MIA)+" zrecznie unika "
            + "zbyt wolno zadanego ciosu.\n"+
            QCIMIE(ja, PL_MIA) + " traci rownowage, lecz po chwili " +
            "odzyskuje ja i kontynuuje tak niefortunnie rozpoczeta walke.\n",
            ({ cel, ja }));

/*
        cel->catch_msg( QCIMIE(ja,PL_MIA) + " traci lekko "
            +"rownowage, zanim jednak zdazysz cos zrobic "
            +"odzysuje ja i walka toczy sie dalej normalnie.\n");
        ja->catch_msg("Tracisz na moment rownowage, szybko jednak "
            +"odzysujesz ja i walka z " + QCIMIE(cel,PL_NAR) +
            " toczy sie dalej normalnie.\n");
*/

        return;
    }

    sila=sila_ciosu(ja, cel, RZ_SZARZA, A_BODY);
    if (objectp(sila)) sila = 0;
    cios = trafienie + sila;
//    cios=random(cios); Wykomentowuje to, bo i tak mamy sume dwoch randomow.
    if (!cel->query_hp()) proc_obr=100;
    else proc_obr = (cios * 100) / cel->query_hp();
    loguj_cios(
        sprintf("Cios: %-7dSila: %-5dTrafienie: %-5dProcent: %-5dProcent max'a: %-5d\n",
            cios, ja->query_stat(SS_STR), sila, proc_obr, cios*100/cel->query_max_hp()), !cel->query_npc());

    cel->heal_hp(-cios);
    numer_obr = jakie_obr(proc_obr);

    if (numer_obr == OBR_SMIERTELNE)
    {
        if (cel->query_hp()) loguj_cios(
            sprintf("UWAGA: %s przezyl szarze z %d hp. Procent obrazen: %d\n",
                C(cel->query_real_name()), cel->query_hp(), proc_obr), !cel->query_npc());
        cel->set_hp(0);
        cel->do_die(ja);
        return;
    }
    wyswietl_opisy(ja, cel, numer_obr);
}

int
jakie_obr(int proc)
{
    switch(proc)
    {
        case 0: return OBR_BRAK;
        case 1..7: return OBR_BLEKKIE;
        case 8..18: return OBR_LEKKIE;
        case 19..32: return OBR_SREDNIE;
        case 33..44: return OBR_CIEZKIE;
        case 45..99: return OBR_BCIEZKIE;
    }
    return OBR_SMIERTELNE;
}

    //A: Nie wiem czy tego rozgraniczenia nie mozna by robic w samym
    // wyswietl opisy()... bez sensu osobno. Tylko tam to jest potrzebne.
    // mam watpliwosci co do rozdzialu tego na lekki i ciezkie
    // Jak z pierwszego ciosu zabierzesz czlowiekowi polowe zdrowia, to juz
    // sa raczej bardzo ciezkie obrazenia, nie ?
    //M: Jakbym to robil w wyswietl_opisy, to i tak bym dal osobna
    // funkcje... uczono mnie, ze im wiecej funkcji tym lepiej..
    // A wartosci sa jak zwykle strzelane...


void
wyswietl_opisy(object ja, object cel, int numer_obr)
{
    object miecz = this_player()->query_weapon(W_RIGHT) || this_player()->query_weapon(W_BOTH);
    // Mor: kurcze albo jestem slepy albo potem nie ma nigdzie opisow
    // zaleznych od broni
    string opis = miecz->short(this_player(),PL_NAR);
    object room = environment(ja);
    string obr;
    string konc1 = cel->koncowka(" mu "," jej ");
    string konc2 = cel->koncowka(" go"," ja");

    if (miecz->query_wt() == W_WARHAMMER)
    {
        switch(numer_obr)
        {
            case OBR_BRAK: obr = "nie wyrzadzajac" + konc1 +
                "jednak zadnej szkody.";
                break;
            case OBR_BLEKKIE: obr = "ledwie" + konc2 + " jednak muskajac.";
                break;
            case OBR_LEKKIE: obr = "lekko"+konc2+" raniac.";
                break;
            case OBR_SREDNIE: obr = "raniac"+konc2+".";
                    break;
            case OBR_CIEZKIE: obr = "ciezko"+konc2+" raniac.";
                break;
            case OBR_BCIEZKIE: obr = "miazdzac"+konc1+"kilka kosci.";
                break;
            case OBR_SMIERTELNE: obr = "miazdzac"+konc1+"kosci. Przeciwni"+cel->koncowka("k","czka")
                +" pada na ziemie "+cel->koncowka("martwy.","martwa.");
        }


        tell_room(room,"Umiejetnie wykorzystujac energie rozpedzonej "
            +"masy, uderza " +QIMIE(cel,PL_BIE)+", "+obr+" \n",({cel,ja}));
        ja->catch_msg("Umiejetnie wykorzystujac energie swojej "
            +"rozpedzonej masy, uderzasz "+ QIMIE(cel,PL_BIE)+ ", "
            + obr +"\n");
        switch(numer_obr)
        {
            case OBR_BRAK: obr = "nie wyrzadzajac ci jednak zadnej szkody.";
                break;
            case OBR_BLEKKIE: obr = "ledwie cie jednak muskajac.";
                break;
            case OBR_LEKKIE: obr = "lekko cie raniac.";
                break;
            case OBR_SREDNIE: obr = "raniac cie.";
                break;
            case OBR_CIEZKIE: obr = "ciezko cie raniac.";
                break;
            case OBR_BCIEZKIE: obr = "miazdzac ci kilka kosci.";
                break;
            case OBR_SMIERTELNE: obr = "miazdzac ci kosci. Padasz "
                +"na ziemie "+cel->koncowka("martwy.","martwa.");
        }

        cel->catch_msg( "Umiejetnie wykorzystujac energie rozpedzonej "
            +"masy, uderza cie, "+obr+ "\n");
    }
    else if (miecz->query_wt()==W_AXE || miecz->query_wt()==W_SWORD)
    {
        switch(numer_obr)
        {
            case OBR_BRAK: obr = "nie wyrzadzajac"+konc1+"jednak zadnej szkody.";
                break;
            case OBR_BLEKKIE: obr = "ledwie"+konc2+" jednak muskajac.";
                break;
            case OBR_LEKKIE: obr = "lekko"+konc2+" raniac.";
                break;
            case OBR_SREDNIE: obr = "raniac"+konc2+".";
                break;
            case OBR_CIEZKIE: obr = "wbijajac"+konc1+"ostrze broni gleboko w cialo.";
                break;
            case OBR_BCIEZKIE: obr = "bardzo gleboko wbijajac ostrze swej broni "
                +"w cialo przeciwnika.";
                break;
            case OBR_SMIERTELNE: obr = "przecinajac"+konc2+" na pol. Przeciwni"+
            cel->koncowka("k","czka")+" pada na ziemie "+cel->koncowka("martwy.","martwa.");
        }


        tell_room(room," Umiejetnie wykorzystujac energie rozpedzonej "
            +"masy, tnie " +QCIMIE(cel,PL_BIE)+", " +obr+ " \n",({cel,ja}));
        ja->catch_msg("Umiejetnie wykorzystujac energie swojej "
            +"rozpedzonej masy, tniesz "+ QCIMIE(cel,PL_BIE)+ ", "
            + obr +"\n");
        switch(numer_obr)
        {
            case OBR_BRAK: obr = "nie wyrzadzajac ci jednak zadnej szkody.";
                break;
            case OBR_BLEKKIE: obr = "ledwie cie jednak muskajac.";
                break;
            case OBR_LEKKIE: obr = "lekko cie raniac.";
                break;
            case OBR_SREDNIE: obr = "raniac cie.";
                break;
            case OBR_CIEZKIE: obr = "wbijajac ci ostrze broni gleboko w cialo.";
                break;
            case OBR_BCIEZKIE: obr = "bardzo gleboko wbijajac ostrze swej broni "
                +"w twoje cialo.";
                break;
            case OBR_SMIERTELNE: obr = "przecinajac cie na pol. Padasz na ziemie "
                +cel->koncowka("martwy.","martwa.");
        }

        cel->catch_msg( "Umiejetnie wykorzystujac energie rozpedzonej "
            +"masy, tnie cie, " + obr + "\n");
    }
    else if (miecz->query_wt()==W_POLEARM) // Mor: odzielenie polearma od
    {                                      // sworda i axa wydaje mi sie
        switch(numer_obr)                  // zagadkowe, ale coz... :)
        {
            case OBR_BRAK: obr = "nie wyrzadzajac"+konc1+"jednak zadnej szkody.";
                break;
            case OBR_BLEKKIE: obr = "ledwie"+konc2+" jednak muskajac.";
                break;
            case OBR_LEKKIE: obr = "lekko"+konc2+" raniac.";
                break;
            case OBR_SREDNIE: obr = "raniac"+konc2+".";
                break;
            case OBR_CIEZKIE: obr = "wbijajac"+konc1+"ostrze broni gleboko w cialo.";
                break;
            case OBR_BCIEZKIE: obr = "bardzo gleboko wbijajac ostrze swej broni "
                +"w cialo przeciwnika.";
                break;
            case OBR_SMIERTELNE: obr = "przebijajac"+konc2+" na wylot. Przeciwni"+cel->koncowka("k","czka")
                +" pada na ziemie "+cel->koncowka("martwy.","martwa.");
        }


        tell_room(room," Umiejetnie wykorzystujac energie rozpedzonej "
            +"masy, atakuje " +QCIMIE(cel,PL_BIE)+", " +obr+ " \n",({cel,ja}));
        ja->catch_msg("Umiejetnie wykorzystujac energie swojej "
            +"rozpedzonej masy, atakuje "+ QCIMIE(cel,PL_BIE)+ ", "
            + obr +"\n");
        switch(numer_obr)
        {
            case OBR_BRAK: obr = "nie wyrzadzajac ci jednak zadnej szkody.";
                break;
            case OBR_BLEKKIE: obr = "ledwie cie jednak muskajac.";
                break;
            case OBR_LEKKIE: obr = "lekko cie raniac.";
                break;
            case OBR_SREDNIE: obr = "raniac cie.";
                break;
            case OBR_CIEZKIE: obr = "wbijajac ci ostrze broni gleboko w cialo.";
                break;
            case OBR_BCIEZKIE: obr = "bardzo gleboko wbijajac ostrze swej broni "
                +"w twoje cialo.";
                break;
            case OBR_SMIERTELNE: obr = "przebijajac cie na wylot. Padasz na ziemie "
                +cel->koncowka("martwy.","martwa.");
        }

        cel->catch_msg( "Umiejetnie wykorzystujac energie rozpedzonej "
            +"masy, atakuje cie, " + obr + "\n");
    }
}
