#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 DOZWOLONE_BRONIE ({W_SWORD,W_AXE,W_CLUB,W_POLEARM})

public void do_boju(object ja, object cel);
int trafil(object kto, object kogo, int czym);
int sila_ciosu(object kto, object kogo);
int jakie_obr(int proc);
void wyswietl_opisy(object ja, object cel, int numer_obr);
void usun_specjala(object komu);



/* Funkcja wywolywana przez komende 'szarzuj'
 */
int 
szarzuj(string str)
{
    float czas;
    object *oblist,p;
    object miecz = TP->query_weapon(W_RIGHT);
    oblist = parse_this(str,"'na' %l:"+PL_BIE);
    if (!miecz) miecz=TP->query_weapon(W_BOTH);
    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;
    }
    
    if (TP->query_prop(OBJ_I_WEIGHT) < 0) // 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 bron, aby moc zaszarzowac.\n");
        return 0;
    }
    
    if (!(member_array(miecz->query_wt(),DOZWOLONE_BRONIE)+1))
    {
        notify_fail("Dobywana przez ciebie bronia nie mozesz"
            +" przeprowadzic szarzy. Pamietaj, ze uzywanie broni"
            +" innych niz miecze, topory i mloty przynosi ujme"
            +" rycerzowi.\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 tej lokacji nie mozesz przeprowadzic szarzy.\n");
        return 0;
    }
    
        if (TP->query_prop(RZ_SPECJAL))
    {
        write("Musisz odczekac troche czasu, zanim bedziesz mogl "
            +"znowu uzyc specjalnego ciosu.\n");
        return 1; // To jest TA szarza... wiec zwracamy 1.
//A: Rodzaje gramatyczne.. sprawdzac
    }

    if (!TP->query_skill(RZ_SZARZA))
    {
        notify_fail("Musisz poznac przynajmniej podstawy tej techniki walki, "
            +"aby moc skutecznie szarzowac.\n");
        return 0;
    }

//A: Dorob sprawdzenie, czy ja z nim nie walcze, i czy on ze mna nie walczy.

    
// Najwidoczniej spelnia podstawowe warunki... teraz zrobimy przygotowanie 
// do ataku.

/* Czas przygotowania: W zaleznosci od skilla:
 *    3sek (skill 0) - 1sek (skill 100)
 */
    czas=(300.0-2.0*itof(TP->query_skill(RZ_SZARZA)))/100.0;
    
    
    write("Przygotowujesz sie do szarzy.\n");
    allbb("przygotowuje sie do szarzy.");
    set_alarm(czas, 0.0, &do_boju(this_player(), oblist[0])); 
    // TP _NIE ZAWSZE_ dziala w alarmach!
    
    return 1;
}

public void
do_boju(object ja, object cel)
{
    object miecz = this_player()->query_weapon(W_RIGHT);
    string opis = miecz->short(this_player(),PL_NAR);
    object room = environment(ja);
    int numer_alarmu;
    int proc_obr;
    int cios;
    int numer_obr; // jaki opis, lekki, sredni, ciezki czy zabity
    string obr;
//A: Dorob sprawdzenie czy wciaz ma miecz w rece.

    string konc = miecz->koncowka("tym","ta");
    if (!present(cel,room))
    {
        actor(({cel}),PL_MIA, " zdazyl ci uciec.");
        allbb("wyglada, jakby sie rozmyslil i juz nie mial zamiaru "
            +"szarzowac.");
//A: Sprawdzenie rodzajow gram...

        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.
    if (ja->query_attack())
    {
        write(" Nie mozesz szarzowac podczas walki.\n");
        return;
    }
    actor("Szarzujesz na", ({cel}),PL_BIE, ".");
    all2act("szarzuje z wyciagnie" + konc + " w gore " + opis + " na", 
        ({ cel }), PL_BIE, ".");
    target("szarzuje na ciebie z wyciagnie" + konc + " w gore " + 
        opis + ".", ({ cel }));

    ja->add_prop(RZ_SPECJAL, set_alarm(PRZERWA, 0.0, "usun_specjala", ja));
//A: Przerwa pomiedzy specjalami nbiie uzalezniona od niczego. Moze to dobzre, moze zle?
    
    if (!trafil(ja, cel, miecz->query_wt()))
    {
        tell_room(room,QCIMIE(cel,PL_MIA)+" zrecznie unika "
            +"zbyt wolno zadanego ciosu.\n", ({cel,ja}));
        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(ja,PL_MIA)+" traci na krotka chwile "
            +"rownowage. 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");
        ja->attack_object(cel);
        return;

//A: To troche glupio wyglada z zewnatrz, dla trzeciej osoby. Lepiej
// Jak by powiazac te dwie informacje ze soba. O uniknieciu ciosu i stracie
// ownowagi.
    }
    cios = sila_ciosu(ja, cel);        
    proc_obr = (cios * 100) / cel->query_hp();
    
//A: Nie lepiej to zgrac w jedna funkcje ?
// Od razu dac heal_hp (-obrazenia) i spradzac czy query_hp == 0
// Zamiast peiprzyc sie z numerami obrazen. A podzial na nie zostawic
// wewnetrznie funkcji wysietl_opisy.. tam tez wyliczac rodzaj.

    numer_obr = jakie_obr(proc_obr);
    wyswietl_opisy(ja, cel, numer_obr);
    cel->heal_hp(-cios);
    if (numer_obr == OBR_SMIERTELNE)
    {
        cel->do_die(ja);
        return;
    }
    tell_room(room, "Dalej walka toczy sie normalnie.\n",({}));    
    ja->attack_object(cel);    
}

public int
trafil(object kto, object kogo, int czym)
{
/*
	Atakujacy			Broniacy
	
	dex				dex
	skill w szarzy			skill w unikach
	wypoczecie			wypoczecie
	skill w broni			-obciazenie
	-obciazenie
*/

//A: Trzeba by pomyslec, czy chcemy to wszystko  rownych proporcjach
//A: Poza tym proponuje uzyc resolve_task
	
    int zr1 = kto->query_stat(SS_DEX);
    int zr2 = kogo->query_stat(SS_DEX);
    int szarza = kto->query_skill(RZ_SZARZA);
    int zm1 = kto->query_fatigue() * 100 / kto->query_max_fatigue();
    int zm2 = kogo->query_fatigue() * 100 / kogo->query_max_fatigue();
    int obc1 = kto->query_encumberance_weight();
    int obc2 = kogo->query_encumberance_weight();
    int uniki = kogo->query_skill(SS_DEFENCE);
    int atak = kto->query_skill(czym);
return (((zr1+szarza+zm1+atak-obc1) - (zr2+zm2+uniki-obc2) - 50 + random(100)) > 0);
}

int 
sila_ciosu(object kto, object kogo)
{
    int str1 = kto->query_stat(SS_STR);
    int tohit = kto->query_weapon(W_RIGHT)->query_hit();
    int szarza = kto->query_skill(RZ_SZARZA);
    int con = kogo->query_stat(SS_CON);
    int waga = kto->query_prop(OBJ_I_WEIGHT);
    int um = kto->query_skill(kto->query_weapon(W_RIGHT)->query_wt());
    int zbr = kogo->query_armour(A_BODY)->query_ac();
    return MAX(((2 * str1 + tohit + szarza + waga + um) - (con + zbr)), 0);
    // sila-wytrzymalosc +-=0;
    // tohit +-= 20-30;
    // szarza/100 < 1;
    // waga/100000 e<0;2>;
    // um/100 <1,5   widac z tego, ze szarza zabiera niewiele...
    //        jakies 20-30 przy rownych przeciwnikach...
    //        Trzeba bedzie tu cos poprawic... na razie nie wiem co. 
    //        Za to, jak widac, przy nierownych przeciwnikach 
    //        Mozna piewrszym ciosem zabic... Musze to z kims obgadac
    //        Ale alvina nie chce meczyc, a silvathraeca nie ma.
//A: To jest bez sensu. Sila ciosu zalezy glownie od to_hit broni.
//A: Akurat to_hit bbroni powinno wplywac na trafienie przy szarzy
//A: A przy obrazeniach powinien miec wplyw pen broni. Poza tym propounje
//A: Skorzystac z marka obliczajacego modified pen. - uzaleznia 
//A: pradziwe obrazenia od skilla i pena broni . Zreszta napisze notke o tym.
//A: Przejrzyj /sys/formul;as.hg
    
}
    
int
jakie_obr(int proc)
{
    switch(proc)
    {
        case 0: return OBR_BRAK;
        case 1..9: return OBR_BLEKKIE; 
        case 10..24: return OBR_LEKKIE;
        case 25..49: return OBR_SREDNIE;
        case 50..74: return OBR_CIEZKIE;
        case 75..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 ?
}

void
wyswietl_opisy(object ja, object cel, int numer_obr)
{
    object miecz = this_player()->query_weapon(W_RIGHT);
    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_CLUB)
    {
        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 " +QCIMIE(cel,PL_BIE)+", "+obr+" \n",({cel,ja}));
        ja->catch_msg("Umiejetnie wykorzystujac energie swojej "
            +"rozpedzonej masy uderzasz "+ 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 = "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)
    {
        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 = "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");
    }
}

void usun_specjala(object komu)
{
//A: Lepiej zamien na bardziej rpgowy tekst.. odzyskalem pelnie
//A: rownowagi, czy cos... cos co by sie laczylo przy okazji
//A: Z tekstem, ze nie mozna jeszcze szarzowac.

    komu->catch_msg("Mozesz znowu uzywac specjalnych ciosow.\n");
    komu->add_prop(RZ_SPECJAL,0);    
//A: Wystarczy chyba albo jedno, albo drugie. remove_prop jjest bardziej
//A: czytelne.
    komu->remove_prop(RZ_SPECJAL);
}
