[Tutorial] - Unit Positions, Fake Miss, Auto - Cast

Tom_Kazansky

<b><font color="RoyalBlue"><font face="Lucida Cons
Tham gia ngày
28/12/06
Bài viết
3,454
Reaction score
462
Trước khi xem tutorial này, ai xem thì nên download Jass NewGen Pack 1.5a
Có vài vấn đề cần đến tool này để giải quyết. Thật ra ko có cũng ko sao nhg nên dùng :-j
---
Trong Jass NewGen có 1 feature gọi là library (thư viện). Trong Jass, muốn gọi 1 function (hàm) nào đó thì hàm đó phải ở trên cái hàm mà chứa dòng lệnh gọi đó. Vì vậy các function trong 1 library sẽ tự động đc đặt lên trên (khi script đc kiểm tra).
Các function cần thiết ta nên cho vào 1 library. library tương tự như map header (vào Trigger Editor, click vào tên map ở bên trái, bên phải là map header).

Scope cũng tương tự library

---
Thứ nhất Tom xin nói về vấn đề "vị trí giữa 2 unit".
Muốn kiểm tra vị trí của 1 unit (unit A) so với 1 unit khác (unit B), ta kiểm tra góc giữa unit B và A, và góc nhìn của B.
Để dễ dàng hơn cho việc kiểm tra, tôi sẽ coi như góc nhìn của B là 0, do vậy, góc giữa B và A cũng sẽ giảm đi một lượng = góc nhìn của B.

Tôi có vài function như sau:
Mã:
scope UnitPositionChecking

    private function Checker takes unit b, unit a, real frontL, real frontR, real backL, real backR returns integer//position of b from a
        local real angle = bj_RADTODEG * Atan2(GetUnitY(b) - GetUnitY(a), GetUnitX(b) - GetUnitX(a))
        if angle >= 0 then
            set angle = angle-GetUnitFacing(a)
        else
            set angle = angle+360-GetUnitFacing(a)
        endif
        if angle < 0 then
            set angle = angle+360
        endif
        
        if angle <= frontL or angle >= frontR then
            return 1
        endif
        if angle >= backL and angle <= backR then
            return 2
        endif
        if angle > backR and angle < frontR then
            return 3
        endif
        if angle > frontL and angle < backL then
            return 4
        endif
        return 0
    endfunction

    function IsUnitInFront takes unit b, unit a returns boolean//b = infront, a = source
        return Checker(b,a,30,330,135,225) == 1
    endfunction

    function IsUnitBehind takes unit b, unit a returns boolean //b = behind, a = source
        return Checker(b,a,30,330,135,225) == 2
    endfunction

    function IsUnitAtSideRight takes unit b, unit a returns boolean//b = atside, a = source
        return Checker(b,a,30,330,135,225) == 3
    endfunction

    function IsUnitAtSideLeft takes unit b, unit a returns boolean//b = atside, a = source
        return Checker(b,a,30,330,135,225) == 4
    endfunction
    
endscope

Nếu bạn ko dùng NewGen , thì chỉ cần copy 5 function trên vào map header thôi (bỏ cái scope endscope đi)
Cách sử dụng:
- Jass user: gọi (call) trực tiếp function IsUnitInFront, IsUnitAtSideLeft, IsUnitAtSideRight, IsUnitBehind.

- GUI user: tạo ra một biến boolean, ví dụ TempCheck và dùng Custom Script để gọi:
Mã:
Custom script:   set udg_TempCheck = IsUnitBehind( udg_TempUnit , udg_TempUnit2 )
Custom script:   set udg_TempCheck = IsUnitInFront( udg_TempUnit , udg_TempSource )
Custom script:   set udg_TempCheck = IsUnitAtSideLeft( udg_TempUnit , udg_TempSource )
Custom script:   set udg_TempCheck = IsUnitAtSideRight( udg_TempUnit , udg_TempSource )
//Source ở đây tương đương với unit B
Sau đó thì kiểm tra biến TempCheck bình thường.

+ Demo spell: Kris Slice (Tom cũng ko nhớ đúng là Kris ko, nghe ở đâu rồi thì phải, chỉ là vừa mới hiện ra trong đầu, nên cứ đặt bừa :D)

Đánh 1 mục tiêu, làm mục tiêu mất 1.5 x Agility + 100 máu.
Nếu caster ở bên trái hoặc bên phải mục tiêu thì mục tiêu sẽ mất nhiều máu hơn
Nếu caster ở đằng sau mục tiêu thì mục tiêu sẽ mất nhiều máu hơn và bị knock back.

Mã:
Kris Slice
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to Kris Slice 
    Actions
        Set TempUnit = (Triggering unit)
        Set TempInt = (Level of Kris Slice  for TempUnit)
        Set TempUnit2 = (Target unit of ability being cast)
        Set TempReal = (100.00 + (1.50 x (Real((Agility of TempUnit (Include bonuses))))))
        [B]Custom script:   set udg_TempCheck = IsUnitBehind( udg_TempUnit , udg_TempUnit2 )[/B]
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                TempCheck Equal to True
            Then - Actions
                Set TempReal = (TempReal + (75.00 + (75.00 x (Real(TempInt)))))
                Set TempLoc = (Position of TempUnit)
                Set TempLoc2 = (Position of TempUnit2)
            //sử dụng Slide kia để Knockback
                Set SlideIndex = (SlideIndex + 1)
                Set SlideUnit[SlideIndex] = TempUnit2
                Set SlideAngle[SlideIndex] = (Angle from TempLoc to TempLoc2)
                Set SlideTick[SlideIndex] = 20
                Set SlideDistance[SlideIndex] = 10.00
                Custom script:   call RemoveLocation( udg_TempLoc )
                Custom script:   call RemoveLocation( udg_TempLoc2 )
            Else - Actions
                [B]Custom script:   set udg_TempCheck = ( IsUnitAtLeftSide( udg_TempUnit , udg_TempUnit2 ) or IsUnitAtRightSide( udg_TempUnit , udg_TempUnit2 ) )[/B]
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        TempCheck Equal to True
                    Then - Actions
                        Set TempReal = (TempReal + (75.00 + (75.00 x (Real(TempInt)))))
                    Else - Actions
        //phần dưới là deal dam và hiên dam lên.
        Floating Text - Create floating text that reads ((String((Integer(TempReal)))) + !) above TempUnit with Z offset 0.00, using font size 10.00, color (100.00%, 0.00%, 0.00%), and 0.00% transparency
        Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
        Floating Text - Change (Last created floating text): Disable permanence
        Floating Text - Change the lifespan of (Last created floating text) to 3.00 seconds
        Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
        Unit - Cause TempUnit to damage TempUnit2, dealing TempReal damage of attack type Chaos and damage type Normal

------------------ Fake Miss -----
Fake Miss, (miss giả) thật ra là tránh damage.

Với 3 trigger (thật ra là 2):

  • DamageRestore Init
  • DamageRestore Add
  • DamageRestore Act

trigger hơi dài nên các bạn mở map ra xem nhé.

cách dùng thì:

  • Đặt 3 biến:
    • DamageRestore_Unit : unit muốn phục hồi tổn thương
    • DamageRestore_Damage : tổn thương mà unit này nhận
    • DamageRestore_Amount : số lượng máu muốn phục hồi
  • Chạy trigger DamageRestore Add


---
Tạo trigger với event unit take damage (khi 1 unit bị mất máu)
Cần 1 biến unit group, tên là TakeDamGroup.
Và 3 trigger:

Mã:
UnitTakeDamageInit
    Events
        Time - Elapsed game time is 0.00 seconds
    Conditions
    Actions
        Custom script:   set bj_wantDestroyGroup = true
        Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
            Loop - Actions
                Unit Group - Add (Picked unit) to TakeDamGroup
                Trigger - Add to UnitTakeDamage <gen> the event (Unit - (Picked unit) Takes damage)
Trigger này để add event "Specific Unit Takes Damage" đối với các unit có sẵn trên bản đồ và add unit đó vào TakeDamGroup. Lần sau nếu có add event nữa thì phải kiểm tra xem unit cần add có trong TakeDamGroup ko, nếu ko thì add, có thì thôi (nếu có mà add tiếp sẽ gây ra bug, trigger sẽ chạy 2 lần)
----
Mã:
UnitTakeDamageDetector
    Events
        Unit - A unit enters (Playable map area)
    Conditions
        ((Triggering unit) is in TakeDamGroup) Equal to False
    Actions
        Unit Group - Add (Triggering unit) to TakeDamGroup
        Trigger - Add to UnitTakeDamage <gen> the event (Unit - (Triggering unit) Takes damage)
Trigger này, khi 1 unit "đi" vào "playable map area" hiểu nôm na là 1 unit xuất hiện ở bản đồ (summon, create with trigger, train,... ) thì add thêm event Unit đó take dam, và add unti đó vào TakeDamGroup.
----
Mã:
UnitTakeDamage
    Events
    Conditions
    Actions
        Trigger - Turn off (This trigger)
        -------- ---------------------- --------
        //spells, or whatever
        -------- ---------------------- --------
        Trigger - Turn on (This trigger)
Khi một unit take damage, trigger này sẽ hoạt động, và để tránh 1 số bug, ta nên "tắt" trigger này đi, xong trigger sẽ "bật" lên.
-------------
Demo spell: Backtrack

Hero sẽ có cơ hội tránh sát thương dưới bất kì hình thức nào.
(ak, sát thương từ phép (magic) còn "attack" là tấn công à ? hic, dịch sao đây ::( )

Trước hết là tạo 1 ability, base từ 1 passive skill nào đó, Vopal Blade hoặc Storm Hammer, viết tooltip, add cho hero.

Viết thêm vào trigger UnitTakeDamage

Mã:
UnitTakeDamage
    Events
    Conditions
    Actions
    Trigger - Turn off (This trigger)
    -------- ---------------------- --------
    Set TempUnit = (Triggering unit)    //đây là unit bị mất máu
    Set TempUnit2 = (Damage source) //đay là unit gây ra damage
    Set TempReal = (Damage taken)   //số damage TempUnit phải chịu
    -------- Backtrack --------
    Set TempInt = (Level of Backtrack  for TempUnit)  //có ability, level > 0
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    	If - Conditions
		TempInt Greater than 0
		(Random integer number between 1 and 100) Less than or equal to (5 + (5 x TempInt))
	Then - Actions
		[COLOR="#0000FF"]Set DamageRestore_Unit = TempUnit
		Set DamageRestore_Damage = TempReal
		Set DamageRestore_Amount = TempReal
		Trigger - Run DamageRestore Add <gen> (ignoring conditions)[/COLOR]
		Special Effect - Create a special effect attached to the hand,left of TempUnit using Abilities\Weapons\WingedSerpentMissile\WingedSerpentMissile.mdl
		Special Effect - Destroy (Last created special effect)
		Floating Text - Create floating text that reads miss above TempUnit with Z offset 0.00, using font size 10.00, color (50.00%, 0.00%, 100.00%), and 0.00% transparency
		Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
		Floating Text - Change (Last created floating text): Disable permanence
		Floating Text - Change the lifespan of (Last created floating text) to 3.00 seconds
	Else - Actions
        -------- ---------------------- --------
        Trigger - Turn on (This trigger)

các dòng màu xanh là cách dùng "DamageRestore", đã nói ở trên.

Thế coi như xong Backtrack.
----- Auto Cast Spell----
tạo 1 auto - cast spell, tât nhiên phải sử dụng system như trên.

Impetus

Attack của hero làm mục tiêu mất nhiều máu hơn, phụ thuộc vào khoảng cách giữa hero và mục tiêu.

Tạo 1 auto cast ability, base từ Poison Arrows (Neutral Hostile)
Tạo 1 buff, base từ Poison , (stacking hay non stacking đều ko sao)
Sau khi bỏ hết các bonus của Poison Arrows, thay buff = buff mới (Poison Arrows cần 3 buff, nhg thay cả 3 bằng 1 buff mới cũng ko sao)

Viết thêm vào trigger UnitTakeDamage

Mã:
Actions
    Trigger - Turn off (This trigger)
    Set TempUnit = (Triggering unit)
    Set TempUnit2 = (Damage source)
    Set TempReal = (Damage taken)
    -------- Backtrack --------
    Set TempInt = (Level of Backtrack  for TempUnit)
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        If - Conditions
		TempInt Greater than 0
		(Random integer number between 1 and 100) Less than or equal to (5 + (5 x TempInt))
	Then - Actions
		[COLOR="#0000FF"]Set DamageRestore_Unit = TempUnit
		Set DamageRestore_Damage = TempReal
		Set DamageRestore_Amount = TempReal
		Trigger - Run DamageRestore Add <gen> (ignoring conditions)[/COLOR]
		Special Effect - Create a special effect attached to the hand,left of TempUnit using Abilities\Weapons\WingedSerpentMissile\WingedSerpentMissile.mdl
		Special Effect - Destroy (Last created special effect)
		Floating Text - Create floating text that reads miss above TempUnit with Z offset 0.00, using font size 10.00, color (50.00%, 0.00%, 100.00%), and 0.00% transparency
		Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
		Floating Text - Change (Last created floating text): Disable permanence
		Floating Text - Change the lifespan of (Last created floating text) to 3.00 seconds
	Else - Actions
    -------- Impetus --------
    Set TempInt = (Level of Impetus  for TempUnit2)  //phải có level
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        If - Conditions
            TempInt Greater than 0
            (TempUnit has buff Impetus ) Equal to True // buff Impetus là buff vừa tạo
        Then - Actions
            Unit - Remove Impetus  buff from TempUnit //remove buff đó đi, ko cần nữa
            Set TempLoc = (Position of TempUnit2)
            Set TempLoc2 = (Position of TempUnit)
            Set TempReal = ((Distance between TempLoc and TempLoc2) x (0.04 x (Real(TempInt))))
            Floating Text - Create floating text that reads (|c0000FFFF+ + ((String((Integer(TempReal)))) + |r)) above TempUnit with Z offset 0.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
            Floating Text - Set the velocity of (Last created floating tex00 degrees
            Floating Text - Change (Last created floating text): Disable permanence
            Floating Text - Change the lifespan of (Last created floating text) to 3.00 seconds
            Unit - Cause TempUnit2 to damage TempUnit, dealing TempReal damage of attack type Chaos and damage type Universal //thêm damage
        Else - Actions
    -------- ---------------------- --------
    Trigger - Turn on (This trigger)

Vì cho dù attack hay đc cast thì ability này cũng làm mục tiêu mất máu và có buff, chỉ cần kiểm tra mục tiêu có buff hay ko, có thì xác định khoảng cách giữa 2 unit và deal thêm damage thôi.

Từ tutorial này, các bạn có thể tạo thêm các auto cast ability khác như: Glaive of Wisdom (deal extra damage = %Int of Hero), Arcane Orb (deal extra damage = % current mana of Hero)
---
Các variable:
TempUnit, TempUnit2 - unit
TempReal - real
TempLoc, TempLoc2 - point

---
Tom đã gửi kèm demo map ở dưới.

do map demo đã sửa ko up đc, nên... Tom sẽ up lại sau
 

Attachments

Chỉnh sửa cuối:
Hiểu :'> chết liền .... :'>
Chắc tui học thêm 1 năm GUI nữa sẽ lên tới cái này ;))
 
Hiểu :'> chết liền .... :'>
Chắc tui học thêm 1 năm GUI nữa sẽ lên tới cái này ;))

hic, ko hiểu thì cứ copy là xong thôi mà, hay ý ông là ko biết dùng ::(
 
hic, ko hiểu thì cứ copy là xong thôi mà, hay ý ông là ko biết dùng ::(

học những ngôn ngữ lập trình như thế này muốn dùng tốt thì phải hiểu, chứ copy cả đoạn script vào nhỡ bị bug ko biết chỗ nào mà fix ?
Nói chung cái này vẫn còn là loại nặng đô, ít nhất là d/v tớ :-<
 
Làm 1 spell non-auto cast thành auto cast như thế nào vậy anh tom
 
Làm 1 spell non-auto cast thành auto cast như thế nào vậy anh tom

Em hãy nói cụ thể hơn (skill nào). Nhg nói chung là ko thể.
 
Em hãy nói cụ thể hơn (skill nào). Nhg nói chung là ko thể.

Chỉ có thể dùng 1 skill gốc dạng autocast (Searing Arrow) rồi A bra ca da bra nó thành theo ý mình :>
 
Anh Tom ơi !!! Giờ em đang muốn học những cái đơn giản của Jass trước rồi đi đến cái phức tạp . Anh có thể vào hoạt động hay là rủ anh HyatHa_dk hoạt động tiếp ở Topic Jass đc ko . Vì ảnh đang hướng dẫn dở dang thì bỏ ... Không biết phải làm sao nữa hic hic
 
Jass thì phải viết, có thể gặp lỗi viết , còn click click thì ko gặp lỗi này, nói chung Jass ngon hơn vì ko limit như click, nhiều thứ phải dùng jass mới xong, cho nên bác nào lập lại topic hướng dẫn cặn kẽ Jass từ đầu tới cuối, em ủng hộ 2 tay 3 chân :D
 
em ko biet sử dụng anh Tom ơi, copy rồi paste ở đâu. anh chỉ cụ thể dc ko
 
Tạo trigger với event unit take damage (khi 1 unit bị mất máu)
Cần 1 biến unit group, tên là TakeDamGroup.
Và 3 trigger:

Mã:
UnitTakeDamageInit
    Events
        Time - Elapsed game time is 0.00 seconds
    Conditions
    Actions
        Custom script:   set bj_wantDestroyGroup = true
        Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
            Loop - Actions
                Unit Group - Add (Picked unit) to TakeDamGroup
                Trigger - Add to UnitTakeDamage <gen> the event (Unit - (Picked unit) Takes damage)
Trigger này để add event "Specific Unit Takes Damage" đối với các unit có sẵn trên bản đồ và add unit đó vào TakeDamGroup. Lần sau nếu có add event nữa thì phải kiểm tra xem unit cần add có trong TakeDamGroup ko, nếu ko thì add, có thì thôi (nếu có mà add tiếp sẽ gây ra bug, trigger sẽ chạy 2 lần)
----
Mã:
UnitTakeDamageDetector
    Events
        Unit - A unit enters (Playable map area)
    Conditions
        ((Triggering unit) is in TakeDamGroup) Equal to False
    Actions
        Unit Group - Add (Triggering unit) to TakeDamGroup
        Trigger - Add to UnitTakeDamage <gen> the event (Unit - (Triggering unit) Takes damage)
Trigger này, khi 1 unit "đi" vào "playable map area" hiểu nôm na là 1 unit xuất hiện ở bản đồ (summon, create with trigger, train,... ) thì add thêm event Unit đó take dam, và add unti đó vào TakeDamGroup.
----
Mã:
UnitTakeDamage
    Events
    Conditions
    Actions
        Trigger - Turn off (This trigger)
        -------- ---------------------- --------
        //spells, or whatever
        -------- ---------------------- --------
        Trigger - Turn on (This trigger)
Khi một unit take damage, trigger này sẽ hoạt động, và để tránh 1 số bug, ta nên "tắt" trigger này đi, xong trigger sẽ "bật" lên.

----- Auto Cast Spell----
tạo 1 auto - cast spell, tât nhiên phải sử dụng system như trên.

Impetus

Attack của hero làm mục tiêu mất nhiều máu hơn, phụ thuộc vào khoảng cách giữa hero và mục tiêu.

Tạo 1 auto cast ability, base từ Poison Arrows (Neutral Hostile)
Tạo 1 buff, base từ Poison , (stacking hay non stacking đều ko sao)
Sau khi bỏ hết các bonus của Poison Arrows, thay buff = buff mới (Poison Arrows cần 3 buff, nhg thay cả 3 bằng 1 buff mới cũng ko sao)

Viết thêm vào trigger UnitTakeDamage

Mã:
Actions
    Trigger - Turn off (This trigger)
    Set TempUnit = (Triggering unit)
    Set TempUnit2 = (Damage source)
    Set TempReal = (Damage taken)
    -------- Backtrack --------
    Set TempInt = (Level of Backtrack  for TempUnit)
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        If - Conditions
            TempInt Greater than 0
            (Random integer number between 1 and 100) Less than or equal to (5 + (5 x TempInt))
        Then - Actions
            Custom script:   call RestoreDamage( udg_TempUnit , udg_TempReal, udg_TempReal )
            Special Effect - Create a special effect attached to the hand,left of TempUnit using Abilities\Weapons\WingedSerpentMissile\WingedSerpentMissile.mdl
            Special Effect - Destroy (Last created special effect)
            Floating Text - Create floating text that reads miss above TempUnit with Z offset 0.00, using font size 10.00, color (50.00%, 0.00%, 100.00%), and 0.00% transparency
            Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
            Floating Text - Change (Last created floating text): Disable permanence
            Floating Text - Change the lifespan of (Last created floating text) to 3.00 seconds
        Else - Actions
    -------- Impetus --------
    Set TempInt = (Level of Impetus  for TempUnit2)  //phải có level
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        If - Conditions
            TempInt Greater than 0
            (TempUnit has buff Impetus ) Equal to True // buff Impetus là buff vừa tạo
        Then - Actions
            Unit - Remove Impetus  buff from TempUnit //remove buff đó đi, ko cần nữa
            Set TempLoc = (Position of TempUnit2)
            Set TempLoc2 = (Position of TempUnit)
            Set TempReal = ((Distance between TempLoc and TempLoc2) x (0.04 x (Real(TempInt))))
            Floating Text - Create floating text that reads (|c0000FFFF+ + ((String((Integer(TempReal)))) + |r)) above TempUnit with Z offset 0.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
            Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
            Floating Text - Change (Last created floating text): Disable permanence
            Floating Text - Change the lifespan of (Last created floating text) to 3.00 seconds
            Unit - Cause TempUnit2 to damage TempUnit, dealing TempReal damage of attack type Chaos and damage type Universal //thêm damage
        Else - Actions
    -------- ---------------------- --------
    Trigger - Turn on (This trigger)

Vì cho dù attack hay đc cast thì ability này cũng làm mục tiêu mất máu và có buff, chỉ cần kiểm tra mục tiêu có buff hay ko, có thì xác định khoảng cách giữa 2 unit và deal thêm damage thôi.

Từ tutorial này, các bạn có thể tạo thêm các auto cast ability khác như: Glaive of Wisdom (deal extra damage = %Int of Hero), Arcane Orb (deal extra damage = % current mana of Hero)
---
Các variable:
TempUnit, TempUnit2 - unit
TempReal - real
TempLoc, TempLoc2 - point

---

thử cái quote này đã.

vì bài trên là nhiều thứ nên có thể lẫn lộn.
 
mà l, jass này là ngôn ngữ nào ?
java? C++? C# ?
 
mà l, jass này là ngôn ngữ nào ?
java? C++? C# ?

Là ngôn ngữ cơ bản của Warcraft III, spell làm bởi Jass mượt, remove leak hiệu quả hơn GUI


_____________
Maiev không chết, anh ấy chỉ bị một cú Echo Slam chí mạng mà tạm thời lên bảng thôi, anh ý sẽ sớm trở lại...
 
Mà cho em hỏi , nếu copy jass qua map khác , nó bị sai biến hay sai cái gì mà ko work vậy anh TOm
 
sai biến, raw id,...
thiếu gì thứ khiến nó ko work
 
Anh Tom cho ví dụ đi ( Hình ảnh minh họa). Lý thuyết với code nhiều cũng khó hiểu lắm:(
 
hình gì chứ, demo map to đùng ở dưới rồi 8-x
 
Back
Top